jdt2jar compiles a JTD schema into a standalone validator JAR at build time. The generated JAR runs on JDK 21+ with no JDK 25+ runtime dependency.
This tool bridges the gap between the interpreter and codegen paths:
- Interpreter (
json-java21-jtd): ideal for infrequent config parsing — simple, no build step, runs on JDK 21+. - Codegen (
json-java21-jtd-codegen): ideal for repeated hot-path validation — ~9x faster, but requires JDK 25+ at runtime. - jdt2jar: pre-compiles schemas into validator JARs at build time (using JDK 25+), then deploys them to any JDK 21+ runtime. Best for CI/CD pipelines, distroless containers, or environments where you want JIT-optimised validators without shipping a JDK 25+ runtime.
Future note:
java.util.jsonhas entered the JDK incubator (jdk.incubator.json). Once the API stabilises in the JDK itself, generated bytecode validators can depend directly on future JDK classes rather than this backport, making them even more efficient with zero library overhead.
jdt2jar <schema.json> [options]Options:
--output <path>: output JAR path (default:<schema-name>-validator.jar)--package <name>: generated package name (default:jtd.generated)--class <name>: validator class name (default:SchemaValidator)--main: include a standalonejava -jarentry point--runtime <version>: target bytecode version (default: 21)--include-sources: write a companion.javafile next to the JAR--help: show usage
A minimal distroless container image is available for offline schema compilation without a full JDK.
docker pull ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest
docker pull ghcr.io/simbo1905/java.util.json.java21/jdt2jar:2026.05.20Requires Docker and JDK 25+ (for the build stage). Build from the repository root:
docker build -t jdt2jar -f jdt2jar/Dockerfile .The container's working directory is /work. Mount your project directory there:
docker run --rm -v "$(pwd):/work" jdt2jar:latest schema.jtd.json --output schema-validator.jar --mainValidate a payload with the generated JAR:
java -jar schema-validator.jar --validate payload.jsonOr validate inside a container:
docker run --rm -v "$(pwd):/work" --entrypoint /jre/bin/java jdt2jar:latest -jar /work/schema-validator.jar --validate /work/payload.jsonFor environments where volume mounts are restricted (e.g., Colima on macOS with projects outside ~/), use the helper script:
./scripts/jdt2jar.sh schema.jtd.json --output schema-validator.jar --mainThe script syncs source to ~/tmp/jdt2jar-work, runs the container, and syncs output back.
- Base:
gcr.io/distroless/base-debian13:nonroot - Runtime: jlink-minimized JDK 25 LTS (~40 MB)
- Total size: ~111 MB disk / ~31 MB content
- User:
nonroot(uid 65532) - Shell: none (distroless)
- Writable directories:
/work(for schema input and JAR output)
syft packages image:ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest
grype ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest