9. Serialization
Requirement prefix: J9.
openEHR canonical JSON (ITS-JSON) is what every openEHR implementation exchanges. A type that serializes but does not read back cannot leave the process.
Round trip#
- J9.1 Every modelled type MUST round-trip: build → serialize → deserialize → compare equal.
- J9.2 A second round trip MUST be byte-identical to the first. A serializer that changes the bytes on the second pass normalised something on the first, and normalising a clinical record silently is what must not happen.
- J9.3 Partial dates, negative durations, fractional seconds, and explicit
UTC offsets MUST survive verbatim (
D3.9,D3.10).
_type#
- J9.4
_typeMUST be emitted wherever the declared attribute type is abstract or has subclasses, and on classes exchanged standalone —COMPOSITION,EHR_STATUS,EHR_ACCESS,FOLDER,HISTORY,EVENT_CONTEXT,ACTIVITY,ISM_TRANSITION,INSTRUCTION_DETAILS. - J9.5
_typeMUST be required on input forDATA_VALUE. Guessing is not available:{"value": "P1D"}is a syntactically validDV_TEXT,DV_URI,DV_DATE, andDV_DURATION, and picking one would turn a measurement into a string in a way nothing downstream could detect. - J9.6 Where
_typeis absent and the choice is decidable by shape, the crate MUST decide by the attribute that carries meaning and MUST NOT lose it:defining_codeforDV_TEXTversusDV_CODED_TEXT(M5.4),relationshipforPARTY_RELATED(M5.13),::count forUID_BASED_ID(I2.20). - J9.7 A
_typenaming a different class than the declared abstract type admits MUST be an error. A_typeon a concrete class MAY be ignored, because there it is redundant.
Reading is lenient, writing is canonical#
- J9.8 The crate MUST accept identifiers written as bare strings where
openEHR specifies
{"value": …}objects. Template tooling emits them, and rejecting them converts a cosmetic divergence into an import failure. - J9.9 The crate MUST ignore attributes it does not model rather than rejecting the document. openEHR adds attributes between minor releases, and a strict reader rejects tomorrow's payload for containing something it does not need.
- J9.10 The crate MUST always write the canonical form, so that leniency normalises on round trip rather than propagating.
- J9.11 Null and empty-list attributes MUST be omitted on output, as ITS-JSON requires.
Canonical bytes for digests#
- J9.12 A canonical byte form MUST be defined for hashing (§11): object keys sorted by Unicode scalar value, no insignificant whitespace, array order preserved.
- J9.13 Numbers MUST NOT be renormalised in the canonical form. Measured precision is data.
- J9.14 Key ordering MUST NOT depend on locale. A locale-dependent digest is not reproducible across hosts.
Recursion#
- J9.15 Deserialization is recursive and its stack cost is a function of
document depth and build profile. The crate MUST document this and MUST NOT
silently impose a depth limit (
S1.15). The measured requirement and the method of measuring it are recorded inaudit.md.