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
-
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.
-
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.
-
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.
-
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:
should produce:
classification: schema
validation: error
not:
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
- All implementations return the same classification for the test matrix above.
- Any JSON object containing an exact root-level
$schema key is classified as schema.
$schema value type or validity does not affect classification.
- Invalid
$schema values are reported during schema validation/dialect resolution.
$$schema does not trigger schema detection unless explicitly specified as a GTS extension.
- Nested
$schema does not classify the enclosing document as a schema.
$id, type, properties, and other schema keywords do not independently trigger schema detection.
- Existing APIs that explicitly specify
schema or instance continue to bypass AUTO detection.
- 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
Align JSON Schema auto-detection across GTS implementations
Summary
gts-spec,gts-rust,gts-go,gts-pythonandgts-tscurrently 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
$schemaproperty.Current behavior
The current implementations behave differently:
{}{"type":"object","properties":{}}{"$id":"gts://gts.x.core.events.type.v1~"}{"$schema":"http://json-schema.org/draft-07/schema#"}{"$schema":"https://json-schema.org/draft/2020-12/schema"}{"$schema":"https://json-schema.org/unknown"}{"$schema":"https://example.com/schema"}{"$schema":"gts.x.core.events.type.v1~"}{"$schema":"anything"}{"$schema":" "}{"$schema":""}{"$schema":null}{"$schema":123}{"$schema":false}{"$schema":{}}{"$schema":[]}{"$$schema":"http://json-schema.org/draft-07/schema#"}{"nested":{"$schema":"http://json-schema.org/draft-07/schema#"}}Problems
gts-rustmixes detection and validation.$schemaproperty with an invalid value can cause the document to be classified as an instance.{"$schema":null}becomesinstanceinstead ofschemafollowed by a schema-validation error.gts-pythonis too restrictive.$schemaonly when the value starts with a knownjson-schema.orgprefix.https://example.com/schemaare therefore incorrectly classified as instances.gts-gorecognizes$$schema.$$schemais not the JSON Schema$schemakeyword.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:
The value of
$schemaMUST 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:
not:
Expected behavior
{}{"type":"object","properties":{}}{"$id":"gts://gts.x.core.events.type.v1~"}$idalone is not used for auto-detection{"$schema":"http://json-schema.org/draft-07/schema#"}{"$schema":"https://json-schema.org/draft/2020-12/schema"}{"$schema":"https://json-schema.org/unknown"}{"$schema":"https://example.com/schema"}{"$schema":"gts.x.core.events.type.v1~"}$schemavalue should fail validation, not detection{"$schema":"anything"}$schemavalue should fail validation, not detection{"$schema":" "}$schemavalue should fail validation, not detection{"$schema":""}$schemavalue should fail validation, not detection{"$schema":null}$schematype should fail validation{"$schema":123}$schematype should fail validation{"$schema":false}$schematype should fail validation{"$schema":{}}$schematype should fail validation{"$schema":[]}$schematype should fail validation{"$$schema":"http://json-schema.org/draft-07/schema#"}$schemakeyword{"nested":{"$schema":"http://json-schema.org/draft-07/schema#"}}$schemaaffects document classificationDetection 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.
No validation of the
$schemavalue is required at this stage.Stage 2: Schema validation / dialect resolution
After classification as
schema:$schemahas the required JSON type;A malformed
$schemadeclaration 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$defstypepropertiesrequiredallOfanyOfoneOfUsing these keywords for detection would create unavoidable false positives because they are also valid property names in ordinary JSON instances.
Likewise,
{},true, andfalseshould remaininstancein AUTO mode unless schema interpretation is explicitly requested by API/context.Required implementation changes
gts-spec
$schemapresence rule.gts-rust
$schemavalue" to "root$schemakey exists".$schematype/value validation to the schema validation stage.gts-go
$schemapresence detection.$$schemaas a schema discriminator unless it is intentionally retained as a documented GTS extension.gts-python
$schemastart withhttp://json-schema.org/orhttps://json-schema.org/.$schemaproperty regardless of its value.Acceptance criteria
$schemakey is classified asschema.$schemavalue type or validity does not affect classification.$schemavalues are reported during schema validation/dialect resolution.$$schemadoes not trigger schema detection unless explicitly specified as a GTS extension.$schemadoes not classify the enclosing document as a schema.$id,type,properties, and other schema keywords do not independently trigger schema detection.schemaorinstancecontinue to bypass AUTO detection.gts-rust,gts-go, andgts-python.Proposed specification wording
Implementation status