A Java implementation of the JSON Type Definition (JTD) specification (RFC 8927). JTD is a schema language for JSON that provides simple, predictable validation with eight mutually-exclusive schema forms.
- RFC 8927 Compliant: Full implementation of the JSON Type Definition specification
- Eight Schema Forms: Empty, Ref, Type, Enum, Elements, Properties, Values, Discriminator
- Stack-based Validation: Efficient iterative validation with comprehensive error reporting
- Immutable Design: All schema types are records, validation uses pure functions
- Rich Error Messages: Standardized error format with instance and schema paths
- Comprehensive Testing: Includes official JTD Test Suite for RFC compliance
import json.java21.jtd.Jtd;
import jdk.sandbox.java.util.json.*;
// Create a JTD schema
String schemaJson = """
{
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"age": { "type": "int32" }
},
"optionalProperties": {
"email": { "type": "string" }
}
}
""";
// Parse and validate
JsonValue schema = Json.parse(schemaJson);
JsonValue data = Json.parse("{\"id\": \"123\", \"name\": \"Alice\", \"age\": 30}");
Jtd validator = new Jtd();
Jtd.Result result = validator.validate(schema, data);
if (result.isValid()) {
System.out.println("Valid!");
} else {
result.errors().forEach(System.out::println);
}JTD defines eight mutually-exclusive schema forms:
Accepts any JSON value:
{}References a definition:
{"ref": "address"}Validates primitive types:
{"type": "string"}Supported types: boolean, string, timestamp, int8, uint8, int16, uint16, int32, uint32, float32, float64
Integer types (int8, uint8, int16, uint16, int32, uint32) validate based on numeric value, not textual representation:
- Valid integers:
3,3.0,3.000,42.00(mathematically integers) - Invalid integers:
3.1,3.14,3.0001(have fractional components)
This follows RFC 8927 §2.2.3.1: "An integer value is a number without a fractional component."
Validates against string values:
{"enum": ["red", "green", "blue"]}Validates homogeneous arrays:
{"elements": {"type": "string"}}Validates objects with required/optional fields:
{
"properties": {
"id": {"type": "string"},
"name": {"type": "string"}
},
"optionalProperties": {
"email": {"type": "string"}
}
}Validates objects with homogeneous values:
{"values": {"type": "string"}}Validates tagged unions:
{
"discriminator": "type",
"mapping": {
"person": {"properties": {"name": {"type": "string"}}},
"company": {"properties": {"name": {"type": "string"}}}
}
}Discriminator Constraints (RFC 8927 §2.2.8):
- Mapping values must be
propertiesschemas (not primitive types) - Mapped schemas cannot have
nullable: true - Mapped schemas cannot define the discriminator key in properties/optionalProperties
- The discriminator field is exempt from additionalProperties validation
These constraints are enforced at compile-time for predictable validation behavior.
Any schema can be made nullable by adding "nullable": true:
{"type": "string", "nullable": true}Schemas can define reusable components:
{
"definitions": {
"address": {
"properties": {
"street": {"type": "string"},
"city": {"type": "string"}
}
}
},
"properties": {
"home": {"ref": "address"},
"work": {"ref": "address"}
}
}Validation errors include standardized information:
[off=45 ptr=/age via=#→field:age] expected int32, got string
- off: Character offset in the JSON document
- ptr: JSON Pointer to the failing value
- via: Human-readable path to the error location
# Build the module
$(command -v mvnd || command -v mvn || command -v ./mvnw) compile -pl json-java21-jtd
# Run tests
$(command -v mvnd || command -v mvn || command -v ./mvnw) test -pl json-java21-jtd
# Run RFC compliance tests
$(command -v mvnd || command -v mvn || command -v ./mvnw) test -pl json-java21-jtd -Dtest=JtdSpecIT
# Run with detailed logging
$(command -v mvnd || command -v mvn || command -v ./mvnw) test -pl json-java21-jtd -Djava.util.logging.ConsoleHandler.level=FINEThe validator uses a stack-based approach for efficient validation:
- Immutable Records: All schema types are immutable records
- Stack-based Validation: Iterative validation prevents stack overflow
- Lazy Resolution: References resolved only when needed
- Comprehensive Testing: Full RFC 8927 compliance test suite
See ARCHITECTURE.md for detailed implementation information.
This implementation is fully compliant with RFC 8927:
- ✅ Eight mutually-exclusive schema forms
- ✅ Standardized error format with instance and schema paths
- ✅ Primitive type validation with proper ranges
- ✅ Definition support with reference resolution
- ✅ Timestamp format validation (RFC 3339 with leap seconds)
- ✅ Discriminator tag exemption from additional properties
- Zero allocations during validation of simple types
- Stack-based validation prevents StackOverflowError
- Early exit on first validation error
- Immutable design enables safe concurrent use
This project is part of the OpenJDK JSON API implementation and follows the same licensing terms.