flashman
← All guides

JSON Schema uniqueItems and deep equality

Design JSON Schema array uniqueness with deep equality, stable object comparison, numeric normalization, explicit business keys, dialect pins, and tests.

2026-09-29 · 8 min read

  • json-schema
  • validation
  • arrays

uniqueItems is a JSON Schema keyword for arrays. When it is true, the instance is valid only if no two items are equal under the schema's equality rules. Those rules follow JSON values, not source formatting and not a single application field.

Teams reach for it when they want a set. It works for that only when the entire item is the identity. Using it as a shortcut for unique email or unique id produces both false duplicates and missed collisions.

Decide what must be unique

Write down whether the array is a set of complete values or a list of records with a key. For a set of strings, numbers, or complete objects, uniqueItems matches the intent. For records, uniqueness of one property needs an application or database constraint that names that property.

  • Document equality as full-value or business-key.
  • Say whether order is significant after uniqueness.
  • Reject null and missing keys explicitly if they matter.
  • Avoid uniqueItems on huge arrays without a size limit.

Normalize before you compare fixtures

Object key order is not part of equality. Numeric text that parses to the same JSON number compares equal. Nested arrays stay ordered, so [1,2] and [2,1] are different. Whitespace outside of strings never creates a distinct value.

Produce fixtures from parsed values, then serialize them. Hand-written JSON that looks different can still be a duplicate, and the reverse is also true when an extra property is present.

Pin the dialect and the validator

Declare the schema dialect and run the same fixtures through every validator on the request path, including gateways and generated clients. Implementations can disagree at the edges of numeric equality or when uniqueItems is combined with composition.

If a validator ignores the keyword, the schema is documentation only. Treat that as a failed dependency, not as a passing test.

Keep business uniqueness outside the keyword

When the real rule is one row per identifier, enforce it where the identifier lives: a database constraint, an explicit application check, or a schema that is limited to that scalar array. Document the error callers should expect.

Do not log entire rejected payloads if items can contain personal data. Log the schema version, array length, and a redacted comparison of the colliding indexes.

Test pairs, not only happy lists

Use Flashman's JSON formatter for instances, diff for a colliding pair, the YAML/JSON converter for schema copies, the regex tester for string items, and the Markdown editor for the uniqueness contract.

Cover reordered object keys, equal numbers with different text, nested arrays, one extra property, duplicate strings that differ by case, empty arrays, a single item, and a validator that does not implement the keyword.

Try these tools