Specification scope: Core only.
For a non-discriminated union, the processor tries each branch in array order. The first match supplies the value’s type identity. There is no later contest to find a more specific candidate.
Move a branch and you may change the meaning of JSON that remains valid before and after the edit. Array order is part of this contract.
First match, not best match
A JSON Structure union is the array form of type:
{
"type": ["string", "int32"]
}
The value must conform to at least one member. When it conforms to several, it is considered to have the type of the first matching member. There is no “narrowest,” “most specific,” or “best” branch calculation after the fact.
Primitive branches often have non-overlapping validation rules. Object types overlap more easily: they may share required properties, and they may permit additional ones. If one object fits both branches, their order decides its interpreted type.
An overlap you can see
A non-discriminated union may contain primitive types and type references. It
must not define an object inline, so compound branches belong under
definitions.
This schema lets the root value be a pickup point or a street address. Both
branches require locationId and label; an object containing only their
shared requirements matches both. PickupPoint comes first because this model
wants that interpretation to win. Both branches explicitly permit additional
properties, so the overlap does not depend on a processor default.
{
"$schema": "https://json-structure.org/meta/core/v0/#",
"$id": "https://schemas.example.com/delivery-destination.json",
"$root": "#/definitions/DeliveryDestination",
"definitions": {
"PickupPoint": {
"type": "object",
"properties": {
"locationId": { "type": "string" },
"label": { "type": "string" },
"lockerBank": { "type": "string" }
},
"required": ["locationId", "label"],
"additionalProperties": true
},
"StreetAddress": {
"type": "object",
"properties": {
"locationId": { "type": "string" },
"label": { "type": "string" },
"street": { "type": "string" },
"city": { "type": "string" }
},
"required": ["locationId", "label"],
"additionalProperties": true
},
"DeliveryDestination": {
"type": [
{ "$ref": "#/definitions/PickupPoint" },
{ "$ref": "#/definitions/StreetAddress" }
]
}
}
}
Consider this value:
{
"locationId": "SEA-042",
"label": "Pine Street pickup",
"lockerBank": "B"
}
It satisfies the required members of both branches. Because PickupPoint is
first, the value is a PickupPoint. Reverse the union members and the same JSON
is considered a StreetAddress.
A validator accepts the value in either order. A code generator, data mapper, or dispatch function still needs one type identity, and the first branch provides it.
Why the union sits under definitions
A schema document’s root object may declare one type, but the root itself must
not use a type array. To make a union the type of document instances, declare
the union under definitions and designate it with $root.
$root and a root-level type are mutually exclusive. Its value is a JSON
Pointer to an existing reusable type under definitions:
{
"$root": "#/definitions/DeliveryDestination",
"definitions": {
"DeliveryDestination": {
"type": ["string", "int32"]
}
}
}
The key under definitions gives the union a reusable location and gives
$root something to point at. It remains a union of referenced or primitive
types, not a new compound type category.
Set the precedence before publishing
Put the branch with the narrower or more useful domain interpretation before a branch that accepts more values. A processor will not rank them for you.
Test the intersections as well as one clean example per branch. For each pair of object branches, construct a value that satisfies their common requirements and verify that the earlier branch is the intended one.
If you do not want precedence to settle an overlap, use a choice with an
explicit selector. A non-discriminated union works when the JSON forms already
separate the alternatives, or when first-match precedence expresses the model.
After publication, reordering its branches is a behavioral change, however
innocent the diff may look.