Skip to content

adapter.json: Add opt-in deterministic JSON array order - #621

Open
thammel wants to merge 1 commit into
eclipse-basyx:developfrom
rwth-iat:fix/573-deterministic-json-array-order
Open

adapter.json: Add opt-in deterministic JSON array order#621
thammel wants to merge 1 commit into
eclipse-basyx:developfrom
rwth-iat:fix/573-deterministic-json-array-order

Conversation

@thammel

@thammel thammel commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Several JSON arrays originate from unordered Python sets: the top-level object lists of an AbstractObjectStore, and the set-valued attributes AssetAdministrationShell.submodel, ConceptDescription.is_case_of and Extension.refers_to. Their iteration order varies between runs because of hash randomization, so serializing the same data twice can yield different files. This makes the output unsuitable for diffing, caching and reproducible builds.

The new opt-in sort_arrays option sorts these arrays by a stable key, while the default behavior stays untouched. Identifiable objects are ordered by their id, references by their type, their key chain and their referred_semantic_id. Deriving the key from these structural attributes rather than from str() or repr() keeps the serialized order independent of the representation methods. The key covers every attribute that Reference.__eq__ considers, because two references differing only in referred_semantic_id are distinct set members whose order would otherwise be decided by the set again.

The option is also exposed as the encoder classes SortingAASToJsonEncoder and SortingStrippedAASToJsonEncoder, following the selection scheme of the existing stripped encoders. Like stripped, the parameter is ignored when a custom encoder class is given, so an encoder remains the single source of truth for how its arrays are ordered.

Not covered by this change

  • The XML adapter, which iterates the same unordered sets and has no equivalent option.
  • The AASX writer, which calls write_aas_json_file without sort_arrays.

Testing

Seven new test cases in JsonSerializationDeterministicOrderTest cover the top-level lists, submodel, is_case_of, refers_to, references differing only in referred_semantic_id, the stripped variant, and the documented "ignored if an encoder is given" contract. They assert the sorted result rather than a specific set order, so they do not depend on set iteration order themselves.

Fixes #573

Several JSON arrays originate from unordered Python sets: the
top-level object lists of an `AbstractObjectStore`, and the set-valued
attributes `AssetAdministrationShell.submodel`,
`ConceptDescription.is_case_of` and `Extension.refers_to`. Their
iteration order varies between runs because of hash randomization, so
serializing the same data twice can yield different files. This makes
the output unsuitable for diffing, caching and reproducible builds.

The new opt-in `sort_arrays` option sorts these arrays by a stable
key, while the default behavior stays untouched. Identifiable objects
are ordered by their `id`, references by their type, their key chain
and their `referred_semantic_id`. Deriving the key from these
structural attributes rather than from `str()` or `repr()` keeps the
serialized order independent of the representation methods. The key
covers every attribute that `Reference.__eq__` considers, because two
references differing only in `referred_semantic_id` are distinct set
members whose order would otherwise be decided by the set again.

The option is also exposed as the encoder classes
`SortingAASToJsonEncoder` and `SortingStrippedAASToJsonEncoder`,
following the selection scheme of the existing stripped encoders. Like
`stripped`, the parameter is ignored when a custom encoder class is
given, so an encoder remains the single source of truth for how its
arrays are ordered.

Fixes eclipse-basyx#573
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

adapter.json: Non-deterministic array order in serialized JSON

1 participant