Skip to content

Normalize

Normalize implements the Message Normalizer EIP. It accepts messages in multiple formats and routes each to a format-specific transformer so the rest of the route sees a single canonical shape. Structurally similar to choice, but semantically dedicated to format detection and conversion.

Processors in this file

NewNormalize

YAML form:

steps:
  - normalize:
      when:
        - starlang: contentType() == "application/xml"
          steps:
            - process: { ref: "xml-to-canonical" }
        - starlang: contentType() == "application/json"
          steps:
            - process: { ref: "json-to-canonical" }
Field Type Default Description
when list of when-clauses required Format-detector predicate + normalization branch pairs. Evaluated in order; the first match wins.
when[].starlang string required Starlang predicate that detects the input format.
when[].steps list required Steps that normalize this format into the canonical form.

Constructor: NewNormalize() *Normalize, with builder method .When(predicate, processor).

How it works:

  1. Iterates Conditions in order.
  2. Calls Predicate.Matches(ctx, ex) for each. The first true wins — that branch runs and Normalize returns.
  3. If no condition matches, returns nil and the exchange passes through unchanged. This is not an error: the caller may already be in a canonical form.

Notes and gotchas:

  • Unlike Choice, Normalize does not support an otherwise branch — if you want a fallback (e.g. reject unknown formats), follow with a validate step.
  • Predicate errors are wrapped as normalize predicate error: ... and returned immediately.
  • For data-driven, dynamically-registerable rules use Normalizer in eip_advanced.go — it supports a fallback processor and records HelixNormalizerMatched.

Examples

workflows:
  - id: ingest-mixed-formats
    trigger: { uri: http://localhost:8080/ingest }
    steps:
      - normalize:
          when:
            - starlang: header("Content-Type") == "application/xml"
              steps:
                - process: { ref: "xml-to-record" }
            - starlang: header("Content-Type") == "text/csv"
              steps:
                - process: { ref: "csv-to-record" }
            - starlang: header("Content-Type") == "application/json"
              steps:
                - process: { ref: "json-to-record" }
      - target: kafka://canonical-records

Source

pkg/processor/normalize.go

See also

  • choice — general content-based routing (no canonical-form semantics).
  • eip_advanced — Normalizer variant with fallback + match tracking.
  • convert — ConvertBody for simple type coercions (string ↔ int ↔ map etc.).