# EDIFACT message parsing

Parse EDIFACT wire text into typed Python objects and serialize them back to the original bytes.

Zato parses EDIFACT wire text into typed Python objects with one call. `parse_edifact` accepts a full interchange with UNA/UNB/UNZ, a bare message starting at UNH, and envelope-less fragments, since mailbox networks often deliver messages in that form. Inside a service, `self.request.edifact` makes this call for you on the text the channel delivered, and everything below applies to the interchange it returns.

## Parsing an interchange {#parsing-an-interchange}

One call parses any EDIFACT text - here, a free-text referral in the Dutch healthcare dialect that ships with the platform:

```python
from zato.edifact import parse_edifact

# Importing a dialect package registers its message classes
import zato.edifact.nl

raw = (
    "UNB+UNOA:1+41007001+41008002+230405:0912+7431'\n"
    "UNH+7431+MEDVRI:1'\n"
    "GGA+Praktijk Rozenburg+Administratie+Praktijk Rozenburg+Kerkstraat:14::Utrecht:3511AB+?+31611223344'\n"
    "DET+24:02:14+09:41'\n"
    "PID+1975:03:18+V+Dijk:van der:Peters:de::M.++BSN999990019'\n"
    "TXT:1+Beste collega'\n"
    "UNT+6+7431'\n"
    "UNZ+1+7431'"
)

interchange = parse_edifact(raw)
```

The result is an `EDIInterchange` with the envelope and the typed messages inside it:

```python
# The UNB header and UNZ trailer are typed segments
sender    = interchange.header.sender.identification
recipient = interchange.header.recipient.identification

# All messages of the interchange, in wire order
for msg in interchange.messages:
    print(msg.unh.identifier.message_type)

# The common case of one message per interchange
msg = interchange.message
```

Each message resolves to its Python class based on the UNH message identifier - `MEDVRI:1` above resolves to the `MEDVRI` class of the Dutch example dialect. To learn how that resolution works and how to register your own classes, see [Dialects and profiles](https://zato.io/docs/dev/healthcare/edifact/dialects/index.html).

## Separators and the UNA segment {#separators-and-the-una-segment}

EDIFACT declares its service characters in an optional UNA segment. The parser recognizes both the standard six-character form and the five-character form seen in production traffic, and messages without any UNA use the default separators:

```python
# UNA present - separators come from the wire
interchange = parse_edifact("UNA:+.? 'UNB+UNOC:3+...")

# No UNA - the defaults apply (: + . ? and ')
interchange = parse_edifact("UNB+UNOA:1+...")

# The separators in effect are always available
print(interchange.separators.element)     # +
print(interchange.separators.component)   # :
print(interchange.separators.terminator)  # '
```

The parser removes release-character escapes (`?+`, `?:`, `?'`) and serialization re-applies them, so element values are always plain text in Python.

## Unknown message types {#unknown-message-types}

A message whose UNH identity is not registered parses into a generic message. Every segment stays navigable by tag and position, and serialization still reproduces the wire text:

```python
interchange = parse_edifact(raw_with_unknown_message)
msg = interchange.message

# All segments with a given tag, in wire order
for nad in msg.segments('NAD'):

    # Positional access - e_1 is the first element
    print(nad.e_1)
```

## Serialization {#serialization}

Many systems that consume EDIFACT have parsed the same byte layout for decades and reject input rendered any other way. The `serialize` method therefore returns the exact wire form, one segment per line - elements that were present stay present, escapes are re-applied and a second parse-serialize cycle returns the same text:

```python
interchange = parse_edifact(raw)
wire = interchange.serialize()

# Individual messages and segments serialize too
wire_msg = msg.serialize()
wire_seg = msg.pid.serialize()
```

## Dict and JSON conversion {#dict-and-json-conversion}

Downstream services and REST APIs often consume JSON rather than EDIFACT wire text. Interchanges, messages and segments all convert to dicts and JSON:

```python
interchange = parse_edifact(raw)

data = interchange.to_dict()
json_text = interchange.to_json(indent=2)

# include_empty=False skips elements without a value
compact = interchange.to_json(include_empty=False)
```

The API follows the same pattern as [HL7 v2 to\_dict and to\_json](https://zato.io/docs/dev/healthcare/hl7/v2/parsing/index.html#convert-to-json), so services that already exchange HL7 v2 as JSON can exchange EDIFACT as JSON with the same method calls.

## See also {#see-also}

- [Field access](https://zato.io/docs/dev/healthcare/edifact/field-access/index.html) - Reading the parsed messages through semantic Python names
- [Dialects and profiles](https://zato.io/docs/dev/healthcare/edifact/dialects/index.html) - How a message resolves to its class and how to define your own
- [Transport patterns](https://zato.io/docs/dev/healthcare/edifact/transport/index.html) - The carriers that deliver interchange text to your services

## Learn more {#learn-more}

- [Healthcare interface engine](https://zato.io/docs/dev/healthcare/) - Clinical messages, FHIR, conversion and operations
- [HL7 v2 parsing](https://zato.io/docs/dev/healthcare/hl7/v2/parsing/) - Messages as typed objects, with field access and validation
- [MLLP channels](https://zato.io/docs/dev/healthcare/hl7v2/mllp/) - Receiving and sending HL7 v2 over MLLP sockets
- [FHIR integrations](https://zato.io/docs/dev/healthcare/hl7/fhir/) - Read and write FHIR resources, with paths, bundles and extensions
- [HL7 v2 to FHIR](https://zato.io/docs/dev/healthcare/hl7/to-fhir/) - Converting v2 messages into FHIR bundles, codes and references included
- [EDIFACT](https://zato.io/docs/dev/healthcare/edifact/) - Parsing interchanges, dialects and the transports they arrive on
- [Transformation](https://zato.io/docs/dev/healthcare/transformation/) - One message in, another standard out, in ordinary Python
- [Audit log](https://zato.io/docs/dev/healthcare/audit-log.html) - Every message with its acknowledgment, searchable by patient identifier
- [AI in clinical interfaces](https://zato.io/docs/dev/healthcare/ai/) - Services calling LLMs and AI agents calling clinical services as tools
