Complete JSON Schema reconstruction and current parity - #1
Conversation
Add the first user-facing guide for building, serializing, and reconstructing JSON schemas. Cover primitive and structured schemas, metadata, required and nullable properties, unions, any-of schemas, local references, and the supported reconstruction subset.
Preserve explicit null defaults independently from unset defaults, make required, nullable, and unique flags reversible, and retain valid empty enum values. Emit numeric property maps and list-shaped object defaults as JSON objects, validate final union and any-of output after nullability is applied, and preserve JSON encoding failures with JSON_THROW_ON_ERROR. Add focused regression coverage for every corrected type and wire shape.
Expose multi-type unions and constrained any-of alternatives through the JSON Schema factory and contract using concrete, Laravel-style return types. Normalize null union members into nullability, reject unsupported or non-string members without coercion, preserve member order, and support shared metadata and explicit defaults. Cover direct construction, closures, nullability, failure paths, and round trips.
Add JsonSchema::fromArray() and rebuild the supported JSON Schema 2020-12 subset without silently weakening recognized validation rules or malformed input. Resolve local references iteratively with per-operation caching, a bounded active path, and a bounded aggregate expansion count. Preserve representable null, composition, enum, default, object-map, and permissive-items forms while rejecting circular, remote, lossy, or structurally conflicting schemas. Exercise every supported type, nested and referenced schemas, exact round trips, resource bounds, invalid keyword values, unsupported assertions, integer limits, and composition failure paths.
Add the JSON Schema guide to the framework documentation navigation and link the package README to the canonical user documentation. Record the public differences from Laravel that developers must account for, including explicit null defaults, sum-type defaults, strict reconstruction failures, supported null and items forms, and bounded local reference expansion.
Mark the package complete in the framework audit checklist and route future readers to the dedicated JSON Schema plan and ledger entry. Record the accepted findings, rejected speculative mechanisms, lifecycle and performance assessment, regression coverage, upstream handoff, validation results, and final no-debt disposition.
Capture the verified Laravel parity surface, serializer and reconstruction defects, approved API improvements, bounded-reference design, and explicit anti-overengineering constraints. Describe the final implementation by owning boundary, include representative code, define the regression and full-gate validation plan, and preserve the completed audit decisions needed for future maintenance.
Rewrite the guide in the simple, direct prose used by first-party Laravel documentation while preserving the original baseline in commit history. Clarify reversible constraints, supported union members, serialization failures, reference limits, nullable one-of reconstruction, permissive array forms, malformed inputs, unsupported keywords, and valid schema forms the fluent builder cannot preserve.
…ectness-parity # Conflicts: # docs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.md
…ectness-parity # Conflicts: # docs/plans/2026-07-12-0900-framework-coroutine-state-lifecycle-audit.md # docs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.md
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThe JSON Schema package adds union and any-of types, raw schema reconstruction, bounded local reference resolution, explicit default tracking, stricter serialization errors, documentation, audit records, and regression tests. ChangesJSON Schema parity and reconstruction
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant JsonSchema
participant Deserializer
participant LocalReferenceResolver
participant Type
Caller->>JsonSchema: call fromArray(schema)
JsonSchema->>Deserializer: deserialize(schema)
Deserializer->>LocalReferenceResolver: resolve local $ref when present
LocalReferenceResolver-->>Deserializer: return bounded schema fragment
Deserializer->>Type: construct reconstructed type
Type-->>Caller: serialize reconstructed schema
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThe PR completes the JSON Schema builder and adds bounded, loss-aware reconstruction from arrays.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| src/json-schema/src/Deserializer.php | Adds bounded reconstruction and now correctly rejects nullable oneOf schemas containing duplicate resolved bare-null branches or another null-accepting branch. |
| tests/JsonSchema/DeserializerTest.php | Covers duplicate inline and referenced null branches, null-overlapping surviving branches, composition ownership, malformed assertions, and reference limits. |
| src/json-schema/src/Serializer.php | Preserves explicit null defaults and object-shaped boundaries while surfacing JSON encoding and empty-composition failures. |
| src/json-schema/src/Types/UnionType.php | Adds strict union-member validation, null normalization, deduplication, and mixed defaults. |
| src/json-schema/src/Types/AnyOfType.php | Adds the composition builder representation and explicit mixed defaults. |
Reviews (2): Last reviewed commit: "fix(json-schema): preserve nullable comp..." | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@docs/plans/2026-08-07-2015-json-schema-correctness-current-parity-and-bounded-reconstruction.md`:
- Around line 439-447: Reorder the workflow in the post-implementation checklist
so the explicit owner-approval gate in the final instruction occurs before
implementation, validation, review sign-off, and all ledger, routing, result,
defect-summary, and completion records. Alternatively, clearly label those
records as post-approval archival actions, while preserving the prohibition on
creating any source, test, documentation, ledger, or bookkeeping commit before
approval.
In `@src/json-schema/src/Types/AnyOfType.php`:
- Around line 14-17: Reject empty composition inputs in AnyOfType::__construct
by throwing InvalidArgumentException before or during normalization of $schemas,
and apply the same validation in UnionType::__construct for empty $types. Update
src/json-schema/src/Types/AnyOfType.php lines 14-17 and
src/json-schema/src/Types/UnionType.php lines 32-55; retain existing behavior
for non-empty inputs.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 93c89d49-b002-4abf-b3bd-41ff41327a67
📒 Files selected for processing (31)
docs/plans/2026-07-12-0900-framework-coroutine-state-lifecycle-audit.mddocs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.mddocs/plans/2026-08-07-2015-json-schema-correctness-current-parity-and-bounded-reconstruction.mdsrc/boost/docs/documentation.mdsrc/boost/docs/json-schema.mdsrc/contracts/src/JsonSchema/JsonSchema.phpsrc/json-schema/README.mdsrc/json-schema/src/Deserializer.phpsrc/json-schema/src/JsonSchema.phpsrc/json-schema/src/JsonSchemaTypeFactory.phpsrc/json-schema/src/Serializer.phpsrc/json-schema/src/Types/AnyOfType.phpsrc/json-schema/src/Types/ArrayType.phpsrc/json-schema/src/Types/BooleanType.phpsrc/json-schema/src/Types/IntegerType.phpsrc/json-schema/src/Types/NumberType.phpsrc/json-schema/src/Types/ObjectType.phpsrc/json-schema/src/Types/StringType.phpsrc/json-schema/src/Types/Type.phpsrc/json-schema/src/Types/UnionType.phptests/JsonSchema/AnyOfTypeTest.phptests/JsonSchema/ArrayTypeTest.phptests/JsonSchema/BooleanTypeTest.phptests/JsonSchema/DeserializerTest.phptests/JsonSchema/IntegerTypeTest.phptests/JsonSchema/NumberTypeTest.phptests/JsonSchema/ObjectTypeTest.phptests/JsonSchema/SerializerTest.phptests/JsonSchema/StringTypeTest.phptests/JsonSchema/TypeTest.phptests/JsonSchema/UnionTypeTest.php
Reject nullable oneOf collapses when more than one branch can match null, including duplicate and reference-resolved null branches. Keep branch-local enums scoped inside nullable anyOf compositions and reject the corresponding oneOf form when flattening would change its meaning. Add counterfactual coverage for exact oneOf cardinality, deliberate anyOf overlap, enum ownership, references, structural siblings, annotations, and existing conflict diagnostics. Clarify the supported reconstruction boundary in the canonical guide and keep the package README limited to genuine additive API differences. Record the two upstream reconstruction defects under their durable audit findings. The checks remain bounded to explicit fromArray calls and add no shared state or request hot-path work.
|
@greptileai @coderabbitai Thanks for the review. Fixed the nullable composition issue and the related enum ownership case:
I did not move empty-composition validation into the constructors. Empty construction is a supported intermediate for nullable-only schemas, and final serialization already rejects compositions that remain empty. I also left the plan ordering unchanged. It explicitly distinguishes uncommitted implementation work from the later approval gate that forbids creating commits. The canonical guide and audit records now describe the supported reconstruction boundary. The package README remains limited to genuine public API differences rather than listing framework bug fixes. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
ast-grep outline src/json-schema/src/Deserializer.php --items all --type method --view expanded
ast-grep outline tests/JsonSchema/DeserializerTest.php --items all --type method --match 'Nullable|nullable|AnyOf|anyOf|OneOf|oneOf|Enum|enum|Reference|reference' --view expanded
printf '\n--- deserializer: composition/enum/reference locations ---\n'
rg -n -C 5 -i 'oneOf|anyOf|nullable|enum|reference|resolve' src/json-schema/src/Deserializer.php
printf '\n--- tests: composition/enum/reference locations ---\n'
rg -n -C 4 -i 'oneOf|anyOf|nullable|enum|reference' tests/JsonSchema/DeserializerTest.phpLength of output: 48495 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- nullable composition implementation ---'
sed -n '135,190p;636,780p' src/json-schema/src/Deserializer.php
printf '%s\n' '--- nullable composition regression tests ---'
sed -n '920,1225p' tests/JsonSchema/DeserializerTest.phpLength of output: 17455
The regression tests cover direct and referenced cases, enum ownership, conflicting enums, structural siblings, annotations, and malformed inputs. Keeping empty compositions valid during construction is correct for nullable-only intermediate states. Final serialization remains the correct validation boundary. 🐇 ✅ ✏️ Learnings added
If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! You are interacting with an AI system. |
|
The implementation handles all three concerns cleanly. Duplicate null in
Branch-local enum ownership — One minor observation for awareness rather than action: The decision not to move empty-composition validation into constructors is sound. The nullable-only intermediate is a legitimate builder state, and serialization is already the right enforcement gate. Looks good overall. Tip: You can customize Greptile's behavior for this repo with |
Summary
This completes the JSON Schema package's current builder surface and makes schema reconstruction explicit, bounded, and reversible.
The package could already build and serialize a useful subset of JSON Schema, but it could not safely reconstruct that subset from arrays. The previous reference path recursively copied schemas, silently weakened several unsupported forms, and could consume enough memory to terminate a long-lived worker. Serialization also lost some valid falsey values and object-shaped boundaries.
What changed
JsonSchema::fromArray()and a dedicated deserializer for the subset represented by the package.anyOfbuilders, including closure-based factory forms and explicit defaults.Design
Reconstruction is operation-local. It does not add container state, coroutine state, locks, I/O, or worker-lived caches. Local
$reftargets are cached only for onefromArray()call, active reference paths are limited to 256 distinct targets, and total schema expansion is capped at 20,000 fragments.The deserializer is intentionally not a general JSON Schema validator. It accepts annotations and extensions that do not change validation, reconstructs the forms the builders can represent faithfully, and fails when a recognized assertion would be dropped or coerced. Applications can continue using a validator for arbitrary third-party schemas.
The existing Laravel-facing builder APIs and named arguments remain intact. The new APIs are additive; newly rejected inputs were previously malformed, unsupported, or reconstructed inaccurately.
Validation
For the detailed implementation design and supported/rejected boundaries, see
docs/plans/2026-08-07-2015-json-schema-correctness-current-parity-and-bounded-reconstruction.md.Summary by CodeRabbit
anyOfcompositions, and reconstruction from schema arrays.nulldefaults.