Skip to content

Latest commit

 

History

History
90 lines (65 loc) · 3.59 KB

File metadata and controls

90 lines (65 loc) · 3.59 KB

jdt2jar

jdt2jar compiles a JTD schema into a standalone validator JAR at build time. The generated JAR runs on JDK 21+ with no JDK 24+ runtime dependency.

Use Case

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 24+ at runtime.
  • jdt2jar: pre-compiles schemas into validator JARs at build time (using JDK 24+), 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 24+ runtime.

Future note: java.util.json has 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.

CLI

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 standalone java -jar entry point
  • --runtime <version>: target bytecode version (default: 21)
  • --include-sources: write a companion .java file next to the JAR
  • --help: show usage

Container Image

A minimal distroless container image is available for offline schema compilation without a full JDK.

Pre-built Image (GitHub Container Registry)

# Pull the latest image
docker pull ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest

# Pull a specific release version
docker pull ghcr.io/simbo1905/java.util.json.java21/jdt2jar:2026.02.05

Build Locally

Requires Docker and JDK 24+ (for the build stage). Build from the repository root:

docker build -t jdt2jar -f jdt2jar/Dockerfile .

Usage

# Show help
docker run --rm ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest --help

# Compile a schema to a validator JAR (using docker cp for file I/O)
cid=$(docker create --name jdt2jar-build ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest /work/person.jtd.json --output /work/person-validator.jar --main)
docker cp person.jtd.json jdt2jar-build:/work/person.jtd.json
docker start -a jdt2jar-build
docker cp jdt2jar-build:/work/person-validator.jar .
docker rm jdt2jar-build

# Validate a payload with the generated JAR
java -jar person-validator.jar --validate payload.json
# Or validate inside a container
cid=$(docker create --name jdt2jar-validate --entrypoint /jre/bin/java ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest -jar /work/person-validator.jar --validate /work/payload.json)
docker cp person-validator.jar jdt2jar-validate:/work/person-validator.jar
docker cp payload.json jdt2jar-validate:/work/payload.json
docker start -a jdt2jar-validate
docker rm jdt2jar-validate

Image Properties

  • Base: gcr.io/distroless/base-debian13:nonroot
  • Runtime: jlink-minimized JDK 24 (~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)

Security Scanning

syft packages image:ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest
grype ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest