Skip to content

Iteration Order

The normative rule is in the Bars specification; this page covers how it appears in fixtures and in the reference implementation's adapters.

{{#each obj }} over a struct (JSON object / YAML map) iterates its entries in insertion order — the order the keys appear in the source document — not sorted or hashed order. A port that iterates a HashMap in hash-bucket order, or that sorts keys before iterating, will produce a different render for any document whose keys are not already alphabetical.

Why this is pinned

Insertion order is the behavior every reference-implementation adapter already had — kxs's JsonObject, yamlkt's YamlMap, and the hand-rolled SimpleStruct all iterate the collection they wrap, and JSON/YAML parsers preserve source key order into those collections. But it was previously unspecified and untested: nothing stopped a future adapter, or a port in another language, from backing a struct with a genuinely unordered map and silently diverging.

Fixture

conformance/render/each-block.json includes a fixture (each-object-non-sorted-keys-preserve-insertion-order) whose keys are deliberately out of alphabetical order (z, a, m). A runner backed by a HashMap (or equivalent) that iterates in hash order, or one that sorts keys before iterating, fails this fixture — the alphabetically-sorted or hash-bucket-ordered output will not match the fixture's expectedOutput, which reflects the source order z, a, m.

What this means for a port's data structures

Whatever container type your port's context/struct model uses to hold document properties, choose one that preserves insertion order on iteration — a LinkedHashMap (JVM), an OrderedDict / dict-with-insertion-order (Python 3.7+, where plain dict already qualifies), a Map (JavaScript, which specifies insertion order), or equivalent. A raw hash table without an ordering guarantee is not sufficient, even if it happens to pass small manual tests — the fixture exists specifically to catch this class of bug with non-alphabetical keys.

See also Number Rendering and Source Locations for the other two "looks like an implementation detail, is actually normative" behaviors pinned by this suite.