Skip to content

Align JSON Schema auto-detection across GTS implementations #103

Description

@Artifizer

Align JSON Schema auto-detection across GTS implementations

Summary

gts-spec, gts-rust, gts-go, gts-python and gts-ts currently use different rules to automatically classify a JSON document as either a JSON Schema or a regular JSON instance.

The implementations should use one consistent rule for auto-detection and keep schema detection separate from schema validation.

JSON Schema itself does not define a reliable generic algorithm for deciding whether arbitrary JSON is intended to be a schema. For example, {}, true, false, and {"type":"object"} may all be valid schemas, but they can also be ordinary JSON instance values.

For GTS auto-detection, the recommended discriminator is therefore the presence of an exact, root-level $schema property.

Current behavior

The current implementations behave differently:

JSON gts-spec gts-rust gts-go gts-python
{} instance instance instance instance
{"type":"object","properties":{}} instance instance instance instance
{"$id":"gts://gts.x.core.events.type.v1~"} instance instance instance instance
{"$schema":"http://json-schema.org/draft-07/schema#"} schema schema schema schema
{"$schema":"https://json-schema.org/draft/2020-12/schema"} schema schema schema schema
{"$schema":"https://json-schema.org/unknown"} schema schema schema schema
{"$schema":"https://example.com/schema"} schema schema schema instance
{"$schema":"gts.x.core.events.type.v1~"} schema schema schema instance
{"$schema":"anything"} schema schema schema instance
{"$schema":" "} schema schema schema instance
{"$schema":""} schema instance schema instance
{"$schema":null} schema instance schema instance
{"$schema":123} schema instance schema instance
{"$schema":false} schema instance schema instance
{"$schema":{}} schema instance schema instance
{"$schema":[]} schema instance schema instance
{"$$schema":"http://json-schema.org/draft-07/schema#"} instance instance schema instance
{"nested":{"$schema":"http://json-schema.org/draft-07/schema#"}} instance instance instance instance

Problems

  1. gts-rust mixes detection and validation.

    • A root $schema property with an invalid value can cause the document to be classified as an instance.
    • Example: {"$schema":null} becomes instance instead of schema followed by a schema-validation error.
  2. gts-python is too restrictive.

    • It recognizes $schema only when the value starts with a known json-schema.org prefix.
    • Custom dialect/meta-schema URIs such as https://example.com/schema are therefore incorrectly classified as instances.
  3. gts-go recognizes $$schema.

    • $$schema is not the JSON Schema $schema keyword.
    • Unless explicitly documented as a GTS extension, it should not affect schema detection.
  4. The behavior is inconsistent across languages, which makes the same JSON document interpreted differently depending on the GTS implementation.

Recommended behavior

Auto-detection should only determine the intent/classification of the root JSON document.

Recommended rule:

if root value is a JSON object
   and the exact root property "$schema" exists:
       classify as SCHEMA
else:
       classify as INSTANCE

The value of $schema MUST NOT affect the initial classification.

Schema validation should happen separately after the document has been classified as a schema.

For example:

{"$schema": null}

should produce:

classification: schema
validation: error

not:

classification: instance

Expected behavior

JSON Expected classification Notes
{} instance Ambiguous; no explicit schema marker
{"type":"object","properties":{}} instance May be a valid schema, but cannot be reliably distinguished from application data
{"$id":"gts://gts.x.core.events.type.v1~"} instance $id alone is not used for auto-detection
{"$schema":"http://json-schema.org/draft-07/schema#"} schema Standard dialect declaration
{"$schema":"https://json-schema.org/draft/2020-12/schema"} schema Standard dialect declaration
{"$schema":"https://json-schema.org/unknown"} schema Schema intent is clear; dialect resolution may fail later
{"$schema":"https://example.com/schema"} schema Custom dialect/meta-schema URIs must be allowed by detection
{"$schema":"gts.x.core.events.type.v1~"} schema Invalid $schema value should fail validation, not detection
{"$schema":"anything"} schema Invalid $schema value should fail validation, not detection
{"$schema":" "} schema Invalid $schema value should fail validation, not detection
{"$schema":""} schema Invalid $schema value should fail validation, not detection
{"$schema":null} schema Invalid $schema type should fail validation
{"$schema":123} schema Invalid $schema type should fail validation
{"$schema":false} schema Invalid $schema type should fail validation
{"$schema":{}} schema Invalid $schema type should fail validation
{"$schema":[]} schema Invalid $schema type should fail validation
{"$$schema":"http://json-schema.org/draft-07/schema#"} instance Not the $schema keyword
{"nested":{"$schema":"http://json-schema.org/draft-07/schema#"}} instance Only a root-level $schema affects document classification

Detection vs validation

The implementation should explicitly separate these two stages.

Stage 1: Auto-detection

Determine whether the root document should be treated as a schema or an instance.

root object contains exact "$schema" key -> schema
otherwise                               -> instance

No validation of the $schema value is required at this stage.

Stage 2: Schema validation / dialect resolution

After classification as schema:

  • verify that $schema has the required JSON type;
  • verify that the value is a valid URI where required by the supported JSON Schema dialect;
  • resolve or recognize the declared dialect/meta-schema;
  • report an unsupported or unknown dialect separately;
  • validate the schema according to that dialect.

A malformed $schema declaration must therefore result in a schema error, not silent reclassification as an instance.

Non-goals

The auto-detector should not attempt heuristic schema recognition based on keywords such as:

  • $id
  • $ref
  • $defs
  • type
  • properties
  • required
  • allOf
  • anyOf
  • oneOf

Using these keywords for detection would create unavoidable false positives because they are also valid property names in ordinary JSON instances.

Likewise, {}, true, and false should remain instance in AUTO mode unless schema interpretation is explicitly requested by API/context.

Required implementation changes

  • gts-spec

    • Keep the current root $schema presence rule.
    • Document that detection does not imply successful schema validation.
  • gts-rust

    • Change detection from "valid/non-empty $schema value" to "root $schema key exists".
    • Move $schema type/value validation to the schema validation stage.
  • gts-go

    • Keep root $schema presence detection.
    • Remove $$schema as a schema discriminator unless it is intentionally retained as a documented GTS extension.
  • gts-python

    • Remove the requirement that $schema start with http://json-schema.org/ or https://json-schema.org/.
    • Detect any exact root $schema property regardless of its value.
    • Validate the value separately.

Acceptance criteria

  1. All implementations return the same classification for the test matrix above.
  2. Any JSON object containing an exact root-level $schema key is classified as schema.
  3. $schema value type or validity does not affect classification.
  4. Invalid $schema values are reported during schema validation/dialect resolution.
  5. $$schema does not trigger schema detection unless explicitly specified as a GTS extension.
  6. Nested $schema does not classify the enclosing document as a schema.
  7. $id, type, properties, and other schema keywords do not independently trigger schema detection.
  8. Existing APIs that explicitly specify schema or instance continue to bypass AUTO detection.
  9. Add the full behavior matrix as shared conformance tests for gts-rust, gts-go, and gts-python.

Proposed specification wording

In AUTO mode, a JSON document is classified as a schema when its root value is an object containing an exact $schema property. The property's value is not evaluated during classification. All other documents are classified as instances. Schema classification indicates document intent only and does not imply that the schema or its $schema declaration is valid. Validation and dialect resolution are performed separately after classification.

Implementation status

  • Spec update
  • e2e tests update
  • gts-go fix
  • gts-rust fix
  • gts-python fix
  • gts-ts fix

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions