Skip to content

JSON Schema: Reference-count guided inlining and schema/schematic merge#2501

Merged
stephenberry merged 4 commits intomainfrom
schema
Apr 15, 2026
Merged

JSON Schema: Reference-count guided inlining and schema/schematic merge#2501
stephenberry merged 4 commits intomainfrom
schema

Conversation

@stephenberry
Copy link
Copy Markdown
Owner

@stephenberry stephenberry commented Apr 15, 2026

JSON Schema: Reference-count guided inlining and schema/schematic merge

Addresses #2469

Overview

$defs entries that are referenced only once are now inlined at their $ref site. Multi-use entries remain in $defs as before.

Before (struct with a single Address field):

{
  "properties": {
    "address": { "$ref": "#/$defs/Address" }
  },
  "$defs": {
    "Address": { "type": "object", "properties": { ... } }
  }
}

After:

{
  "properties": {
    "address": { "type": "object", "properties": { ... } }
  }
}

When a type is referenced from multiple sites, it stays in $defs with $ref as before.

Implementation

The inlining operates on the typed schema tree before serialization — no JSON parsing/re-serialization round-trip.

  1. count_schema_refs — walks the tree counting $ref string occurrences
  2. try_inline_ref — for single-use $ref nodes, moves the definition from $defs into the reference site, merging any sibling metadata (e.g. title, description)
  3. inline_single_use_refs — recursive traversal that applies inlining at every reference site (properties, items, additionalProperties, oneOf, prefixItems), with chained resolution for nested single-use types
  4. prune_inlined_defs — removes consumed entries; drops $defs entirely when empty

Unified schema type

schema and detail::schematic are merged into a single schema struct. This eliminates the type mismatch that previously prevented typed inlining (properties stored schema but definitions were schematic).

  • User-facing API unchangedglz::json_schema<T> specializations continue to work with designated initializers (schema x{.description = "...", .minimum = 0})
  • Structural fields (properties, items, oneOf, defs, etc.) are at the bottom of the struct, all std::optional defaulting to null
  • items and additionalProperties use std::shared_ptr<schema> to break the recursive type cycle while keeping schema copyable
  • Metadata (glz::meta<schema>) moved to an external specialization (required because the self-referential container members need the type to be complete)

Other changes

  • merge_schema_attrs applies user json_schema metadata with merge semantics rather than wholesale assignment, preserving generated fields (e.g. a user-specified minimum no longer discards the type's maximum)
  • make_primitive_schema returns std::shared_ptr<schema> (was schema) to match the new items/additionalProperties type
  • openapi.hpp and http_server.hpp updated from detail::schematic to schema

@stephenberry stephenberry linked an issue Apr 15, 2026 that may be closed by this pull request
@packit-as-a-service
Copy link
Copy Markdown

@packit-as-a-service
Copy link
Copy Markdown

@stephenberry stephenberry changed the title Remove glz::detail::schematic and use a single glz::schema Reference-count guided inlining and schema/schematic merge Apr 15, 2026
@stephenberry stephenberry changed the title Reference-count guided inlining and schema/schematic merge JSON Schema: Reference-count guided inlining and schema/schematic merge Apr 15, 2026
@stephenberry stephenberry merged commit 5339785 into main Apr 15, 2026
49 checks passed
@stephenberry stephenberry deleted the schema branch April 15, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Schema Optimziation: reference count guided inlining

1 participant