Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
fd92756
Issue #29 Add OpenRPC schema validation IT and resources
simbo1905 Sep 15, 2025
4671f2b
Fix CI configuration: use Java 21 and correct test count
openhands-agent Sep 15, 2025
86b73bc
fix: improve JsonSchemaCheckIT metrics reporting for defensible compa…
simbo1905 Sep 15, 2025
2b5bdfe
docs: update compatibility claims with measured metrics from JsonSche…
simbo1905 Sep 15, 2025
65da474
Merge pull request #32 from simbo1905/fix/jsonschema-metrics-31
simbo1905 Sep 15, 2025
9606396
more features
simbo1905 Sep 15, 2025
efd25bd
pack5
simbo1905 Sep 16, 2025
d8ca22a
pack6
simbo1905 Sep 16, 2025
a7480cb
more tests
simbo1905 Sep 16, 2025
302729f
wip broken test
simbo1905 Sep 16, 2025
91367bb
fixed
simbo1905 Sep 17, 2025
0b8d998
wip
simbo1905 Sep 17, 2025
2f0cc1a
wip
simbo1905 Sep 17, 2025
296c7d4
tests pass
simbo1905 Sep 18, 2025
6f06484
back to wip k2
simbo1905 Sep 18, 2025
47c13d2
offical logging advice
simbo1905 Sep 18, 2025
496edbc
comments
simbo1905 Sep 18, 2025
2c1b752
docs
simbo1905 Sep 18, 2025
2422b1d
wip
simbo1905 Sep 18, 2025
dbcb26c
wip
simbo1905 Sep 18, 2025
418f393
wip
simbo1905 Sep 18, 2025
900325b
wip two errors two failures
simbo1905 Sep 19, 2025
a12f139
all tests pass
simbo1905 Sep 19, 2025
d48335b
notes
simbo1905 Sep 19, 2025
45b3ae7
test working less logging
simbo1905 Sep 20, 2025
257f004
state
simbo1905 Sep 20, 2025
9ef842a
fixed relative paths
simbo1905 Sep 20, 2025
c608234
better data structures
simbo1905 Sep 20, 2025
639b274
pre tidy-up
simbo1905 Sep 20, 2025
0227fbd
context stack
simbo1905 Sep 20, 2025
c093d27
logging
simbo1905 Sep 20, 2025
69d692a
docs: update schema compatibility metrics (strict headline + overall)…
simbo1905 Sep 20, 2025
2ca9300
ci: update expected test totals to reflect new suite counts (guard ag…
simbo1905 Sep 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,36 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Set up JDK 24
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '24'
java-version: '21'
cache: 'maven'

- name: Build and verify
run: mvn -B -DskipITs=false -DskipTests=false verify

- name: Assert test count (no tests silently skipped)
run: |
python3 - <<'PY'
import os, xml.etree.ElementTree as ET, sys
totals={'tests':0,'failures':0,'errors':0,'skipped':0}
for dirpath,_,files in os.walk('.'):
if 'target' not in dirpath: continue
if 'surefire-reports' not in dirpath and 'failsafe-reports' not in dirpath: continue
for fn in files:
if not fn.endswith('.xml'): continue
p=os.path.join(dirpath,fn)
try:
r=ET.parse(p).getroot()
for k in totals: totals[k]+=int(r.get(k,'0'))
except Exception:
pass
exp_tests=1908
exp_skipped=713
if totals['tests']!=exp_tests or totals['skipped']!=exp_skipped:
print(f"Unexpected test totals: {totals} != expected tests={exp_tests}, skipped={exp_skipped}")
sys.exit(1)
print(f"OK totals: {totals}")
PY
606 changes: 349 additions & 257 deletions AGENTS.md

Large diffs are not rendered by default.

23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,28 @@ var result = schema.validate(
// result.valid() => true
```

Compatibility: runs the official 2020‑12 JSON Schema Test Suite on `verify`; in strict mode it currently passes about 71% of applicable cases.
Compatibility: runs the official 2020‑12 JSON Schema Test Suite on `verify`; **strict compatibility is 61.6%** (1024 of 1,663 validations). [Overall including all discovered tests: 56.2% (1024 of 1,822)].

### JSON Schema Test Suite Metrics

The validator now provides defensible compatibility statistics:

```bash
# Run with console metrics (default)
./mvn-test-no-boilerplate.sh -pl json-java21-schema

# Export detailed JSON metrics
./mvn-test-no-boilerplate.sh -pl json-java21-schema -Djson.schema.metrics=json

# Export CSV metrics for analysis
./mvn-test-no-boilerplate.sh -pl json-java21-schema -Djson.schema.metrics=csv
```

**Current measured compatibility**:
- **Strict (headline)**: 61.6% (1024 of 1,663 validations)
- **Overall (incl. out‑of‑scope)**: 56.2% (1024 of 1,822 discovered tests)
- **Test coverage**: 420 test groups, 1,663 validation attempts
- **Skip breakdown**: 65 unsupported schema groups, 0 test exceptions, 647 lenient mismatches

## Building

Expand Down
92 changes: 0 additions & 92 deletions json-java21-schema/AGENTS.md

This file was deleted.

47 changes: 43 additions & 4 deletions json-java21-schema/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

Stack-based JSON Schema validator using sealed interface pattern with inner record types.

- Draft 2020-12 subset: object/array/string/number/boolean/null, allOf/anyOf/not, if/then/else, const, $defs and local $ref (including root "#")
- Draft 2020-12 subset: object/array/string/number/boolean/null, allOf/anyOf/not, if/then/else, const, format (11 validators), $defs and local $ref (including root "#")
- Thread-safe compiled schemas; immutable results with error paths/messages
- **Novel Architecture**: This module uses an innovative immutable "compile many documents (possibly just one) into an immutable set of roots using a work stack" compile-time architecture for high-performance schema compilation and validation. See `AGENTS.md` for detailed design documentation.

Quick usage

Expand All @@ -22,18 +23,29 @@ Compatibility and verify

- The module runs the official JSON Schema Test Suite during Maven verify.
- Default mode is lenient: unsupported groups/tests are skipped to avoid build breaks while still logging.
- Strict mode: enable with -Djson.schema.strict=true to enforce full assertions. In strict mode it currently passes about 71% of applicable cases.
- Strict mode: enable with `-Djson.schema.strict=true` to enforce full assertions.
- Measured compatibility (headline strictness): 61.6% (1024 of 1,663 validations)
- Overall including all discovered tests: 56.2% (1024 of 1,822)
- Test coverage: 420 test groups, 1,663 validation attempts, 65 unsupported schema groups, 0 test exceptions, 647 lenient mismatches
- Detailed metrics available via `-Djson.schema.metrics=json|csv`

How to run

```bash
# Run unit + integration tests (includes official suite)
mvn -pl json-java21-schema -am verify
./mvn-test-no-boilerplate.sh -pl json-java21-schema

# Strict mode
mvn -Djson.schema.strict=true -pl json-java21-schema -am verify
./mvn-test-no-boilerplate.sh -pl json-java21-schema -Djson.schema.strict=true
```

OpenRPC validation

- Additional integration test validates OpenRPC documents using a minimal, self‑contained schema:
- Test: `src/test/java/io/github/simbo1905/json/schema/OpenRPCSchemaValidationIT.java`
- Resources: `src/test/resources/openrpc/` (schema and examples)
- Thanks to OpenRPC meta-schema and examples (Apache-2.0): https://github.com/open-rpc/meta-schema and https://github.com/open-rpc/examples

## API Design

Single public interface with all schema types as inner records:
Expand Down Expand Up @@ -145,3 +157,30 @@ if (!result.valid()) {
}
}
```

### Format Validation

The validator supports JSON Schema 2020-12 format validation with opt-in assertion mode:

- **Built-in formats**: uuid, email, ipv4, ipv6, uri, uri-reference, hostname, date, time, date-time, regex
- **Annotation by default**: Format validation is annotation-only (always passes) unless format assertion is enabled
- **Opt-in assertion**: Enable format validation via:
- `JsonSchema.Options(true)` parameter in `compile()`
- System property: `-Djsonschema.format.assertion=true`
- Root schema flag: `"formatAssertion": true`
- **Unknown formats**: Gracefully handled with logged warnings (no validation errors)

```java
// Format validation disabled (default) - always passes
var schema = JsonSchema.compile(Json.parse("""
{"type": "string", "format": "email"}
"""));
schema.validate(Json.parse("\"invalid-email\"")); // passes

// Format validation enabled - validates format
var schema = JsonSchema.compile(Json.parse("""
{"type": "string", "format": "email"}
"""), new JsonSchema.Options(true));
schema.validate(Json.parse("\"invalid-email\"")); // fails
schema.validate(Json.parse("\"[email protected]\"")); // passes
```
71 changes: 71 additions & 0 deletions json-java21-schema/mvn-test-no-boilerplate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/bin/bash

# Strip Maven test boilerplate - show compile errors and test results only
# Usage: ./mvn-test-no-boilerplate.sh [maven test arguments]
#
# Examples:
# ./mvn-test-no-boilerplate.sh -Dtest=RefactorTests
# ./mvn-test-no-boilerplate.sh -Dtest=RefactorTests#testList -Djava.util.logging.ConsoleHandler.level=INFO
# ./mvn-test-no-boilerplate.sh -Dtest=RefactorTests#testList -Djava.util.logging.ConsoleHandler.level=FINER
#
# For running tests in a specific module:
# ./mvn-test-no-boilerplate.sh -pl json-java21-api-tracker -Dtest=CompilerApiLearningTest
#
# The script automatically detects if mvnd is available, otherwise falls back to mvn

# Detect if mvnd is available, otherwise use mvn
if command -v mvnd &> /dev/null; then
MVN_CMD="mvnd"
else
MVN_CMD="mvn"
fi

timeout 120 $MVN_CMD test "$@" 2>&1 | awk '
BEGIN {
scanning_started = 0
compilation_section = 0
test_section = 0
}

# Skip all WARNING lines before project scanning starts
/INFO.*Scanning for projects/ {
scanning_started = 1
print
next
}

# Before scanning starts, skip WARNING lines
!scanning_started && /^WARNING:/ { next }

# Show compilation errors
/COMPILATION ERROR/ { compilation_section = 1 }
/BUILD FAILURE/ && compilation_section { compilation_section = 0 }

# Show test section
/INFO.*T E S T S/ {
test_section = 1
print "-------------------------------------------------------"
print " T E S T S"
print "-------------------------------------------------------"
next
}

# In compilation error section, show everything
compilation_section { print }

# In test section, show everything - let user control logging with -D arguments
test_section {
print
}

# Before test section starts, show important lines only
!test_section && scanning_started {
if (/INFO.*Scanning|INFO.*Building|INFO.*resources|INFO.*compiler|INFO.*surefire|ERROR|FAILURE/) {
print
}
# Show compilation warnings/errors
if (/WARNING.*COMPILATION|ERROR.*/) {
print
}
}
'
Loading