# JSON Format

Tediware represents every EDI transaction set as JSON. When a partner sends you EDI, Tediware translates each transaction set into this JSON and hands it to your system. When you send EDI to a partner, your mapping produces JSON in this same shape and Tediware writes the X12 for you. You work with JSON; Tediware handles the EDI.

## Document Structure

A translated document is a single transaction set, divided into up to three sections:

- `heading`: the segments before the detail area, holding the transaction's metadata.
- `detail`: the repeating body of the document, such as line items or stops.
- `summary`: totals and the transaction trailer.

Only the sections actually present in the document appear. The interchange and group envelope (ISA, GS, GE, IEA) is not part of the transaction set JSON. Tediware manages the envelope separately.

Here is a complete translated 856 Ship Notice:

```json
{
  "heading": {
    "transaction_set_header_ST": {
      "transaction_set_identifier_code_01": "ship_notice_manifest_856",
      "transaction_set_control_number_02": "0001"
    },
    "beginning_segment_for_ship_notice_BSN": {
      "transaction_set_purpose_code_01": "original_00",
      "shipment_identification_02": "SHIP-0001",
      "date_03": "20260203",
      "time_04": "120000"
    }
  },
  "detail": {
    "shipment_S_HL_loop": [
      {
        "hierarchical_level_HL": {
          "hierarchical_id_number_01": "1",
          "hierarchical_level_code_03": "shipment_S",
          "hierarchical_child_code_04": "additional_subordinate_hl_data_segment_in_this_hierarchical_structure_1"
        },
        "measurements_MEA": [
          {
            "measurement_reference_id_code_01": "physical_dimensions_PD",
            "measurement_qualifier_02": "weight_WT",
            "measurement_value_03": 100.0,
            "composite_unit_of_measure_04": {
              "_composite": true,
              "unit_or_basis_for_measurement_code_01": "pound_LB",
              "exponent_02": 1.0,
              "multiplier_03": 1.0
            }
          },
          {
            "measurement_reference_id_code_01": "counts_CT",
            "measurement_qualifier_02": "height_HT",
            "measurement_value_03": 5.5,
            "composite_unit_of_measure_04": {
              "_composite": true,
              "unit_or_basis_for_measurement_code_01": "inch_IN"
            }
          }
        ],
        "item_I_HL_loop": [
          {
            "hierarchical_level_HL": {
              "hierarchical_id_number_01": "2",
              "hierarchical_parent_id_number_02": "1",
              "hierarchical_level_code_03": "item_I"
            },
            "item_identification_LIN": {
              "assigned_identification_01": "1",
              "product_service_id_qualifier_02": "u_p_c_consumer_package_code_1_5_5_1_UP",
              "product_service_id_03": "012345678905"
            },
            "item_detail_shipment_SN1": {
              "number_of_units_shipped_02": 24.0,
              "unit_or_basis_for_measurement_code_03": "each_EA"
            }
          }
        ]
      }
    ]
  },
  "summary": {
    "transaction_totals_CTT": {
      "number_of_line_items_01": 2
    },
    "transaction_set_trailer_SE": {
      "number_of_included_segments_01": 10,
      "transaction_set_control_number_02": "0001"
    }
  }
}
```

## Field Names

Every key carries its X12 meaning, so you do not have to memorize segment and element codes.

- Segment keys are the segment name followed by its X12 code, for example `transaction_set_header_ST` and `measurements_MEA`.
- Element keys are the element name followed by its two-digit position, for example `transaction_set_control_number_02` and `measurement_value_03`.

The naming is lossless. To recover the raw X12 code, take the text after the last underscore: `transaction_set_header_ST` yields the segment code `ST`, and `measurement_value_03` yields position `03`.

## Values

### Coded values

A coded element carries both its meaning and its code, joined by an underscore. In the example above, `transaction_set_purpose_code_01` is `original_00`: the readable name `original` followed by the X12 code `00`. Recover the bare code the same way you would a segment code, by splitting on the last underscore:

```javascript
const purposeCode = doc.heading
  .beginning_segment_for_ship_notice_BSN
  .transaction_set_purpose_code_01
  .split("_")
  .pop();
// "00"
```

### Numbers

Numeric elements are native JSON numbers, not strings. Integer elements (X12 type N0) become integers, and elements with decimal places (N2, R, and similar) become floating-point numbers. In the example, `number_of_line_items_01` is `2` and `measurement_value_03` is `100.0`.

Identifiers, codes, dates, and free text remain strings.

### Dates and times

Dates and times are kept as their digits, exactly as they appear in the EDI. The example's `date_03` is `"20260203"`, a string rather than a formatted timestamp, because X12 date and time formats vary from element to element. Read the qualifier element in the same segment to learn how to interpret it.

## Loops

A repeating group of segments becomes a JSON array, and its key ends in `_loop`. In the example, the shipment hierarchy is `shipment_S_HL_loop`, and within it the items are `item_I_HL_loop`. Hierarchical (HL) loops are nested: a child loop appears inside its parent.

Iterate these arrays with ordinary tools:

```javascript
for (const shipment of doc.detail.shipment_S_HL_loop) {
  for (const item of shipment.item_I_HL_loop ?? []) {
    console.log(item.item_identification_LIN.product_service_id_03);
  }
}
```

## Composite Elements

A composite element packs several components into one element position. In JSON it becomes an object marked with `"_composite": true`, with one key per component, named and position-suffixed like any other element.

A fully populated composite:

```
MEA*PD*WT*100*LB:1:1~
```

```json
{
  "_composite": true,
  "unit_or_basis_for_measurement_code_01": "pound_LB",
  "exponent_02": 1.0,
  "multiplier_03": 1.0
}
```

When trailing components are absent, their keys are simply omitted:

```
MEA*CT*HT*5.5*IN~
```

```json
{
  "_composite": true,
  "unit_or_basis_for_measurement_code_01": "inch_IN"
}
```

When an interior component is absent, the EDI preserves the gap as a doubled component separator, and the JSON omits the missing key:

```
MEA*PD*WT*100*LB::5~
```

```json
{
  "_composite": true,
  "unit_or_basis_for_measurement_code_01": "pound_LB",
  "multiplier_03": 5.0
}
```

## Authoring JSON for Outbound EDI

For outbound, your mapping produces JSON in this same representation and Tediware writes the X12. A few specifics apply:

- The structure and key names are identical to the translated format above.
- Coded values use the bare X12 code, such as `"00"` or `"LB"`, matching the allowed values in your partner's implementation schema. This is the one difference from inbound, where values carry the descriptive prefix (`pound_LB`).
- Numeric fields accept either a JSON number or a numeric string: `100.0` and `"100.0"` are both valid.
- Composites use the same `"_composite": true` object. Omit trailing components you do not need and Tediware trims them. To leave an interior component empty, omit its key and Tediware preserves the gap.

Your partner's implementation schema is the authoritative contract for which segments, elements, and codes are valid in a given transaction set.
