Skip to content

OpenAPI 3.1 / JSON Schema 2020-12: $ref+description fix and further feature support - #382

Merged
jemacineiras merged 2 commits into
sngular:mainfrom
joseegman-idoneea:feat/openapi31-completeness
Jul 24, 2026
Merged

OpenAPI 3.1 / JSON Schema 2020-12: $ref+description fix and further feature support#382
jemacineiras merged 2 commits into
sngular:mainfrom
joseegman-idoneea:feat/openapi31-completeness

Conversation

@joseegman-idoneea

@joseegman-idoneea joseegman-idoneea commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Builds on #381 (already merged into main) and adds further OpenAPI 3.1 / JSON Schema 2020-12 support found while auditing the schema generator.

Structural correctness fixes

Feature Before After
$defs schema source #/$defs/* unresolved → NPE / missing model collected & generated
prefixItems / items: false element type lost/invalid List<Object>
scalar type: "null" invalid null Java type Object
nullability (nullable:true or ["T","null"]) could emit @NotNull on a nullable field no spurious @NotNull
patternProperties empty POJO Map<String, V>
3.1 binary (contentEncoding/contentMediaType) plain String MultipartFile
description + example/examples dropped emitted on @Schema (incl. the $ref sibling description)

The description/example(examples) propagation applies to both the OpenAPI and AsyncAPI model generators; committed assets are regenerated accordingly. The Lombok model template does not use @Schema, so descriptions are not emitted there (unchanged).

Tests

New regression testOpenApi31Completeness exercises $defs, prefixItems, type:"null", the nullable-but-required case, patternProperties, contentEncoding, plus description/example/examples in one spec. Full multiapi-engine suite: 110/110 passing (mvn clean test).

Documented limitations (non-breaking, deferred as larger work)

  • Multi-type unions (["string","integer"]) still pick the first concrete type — the current tested behaviour; a real union type model is a separate feature.
  • contains / minContains / maxContains / propertyNames / unevaluated* / dependent* / if-then-else — parsed-through and ignored today (no crash); enforcement needs new Bean-Validation validator classes for keywords with little real-world OpenAPI usage.
  • info.summary / license.identifier — API-doc metadata, no effect on generated code.
  • $id / $anchor resolution and $schema / $dynamicRef — ignored non-fatally; anchor-based resolution would need an anchor index in the resolver.

Version bump 6.4.26.5.0 (new features).

🤖 Generated with Claude Code

@codacy-production

codacy-production Bot commented Jul 24, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 45 complexity · 0 duplication

Metric Results
Complexity 45
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Follow-up to the $ref+description fix, addressing further 3.1 gaps found in an
audit of the schema generator. Structural correctness fixes (narrow blast
radius; only affect specs using these constructs):

- $defs: collect top-level `$defs` as a schema source and resolve
  `$ref: '#/$defs/...'` (ApiTool.getComponentSchemas). Models under $defs now
  generate and are referenceable.
- prefixItems / items:false: tuple arrays and `items:false` degrade to
  List<Object> instead of an empty/invalid element type.
- type:"null": a scalar null type degrades to Object instead of emitting an
  invalid `null` Java type.
- nullability: a field that is nullable (3.0 `nullable:true` or the 3.1
  ["T","null"] idiom) is no longer marked required, so no spurious @NotNull is
  generated (ApiTool.isNullable).
- patternProperties: an object with patternProperties maps to Map<String,V>
  instead of an empty POJO.
- 3.1 binary strings: `contentEncoding` / `contentMediaType` are recognised as
  binary (MultipartFile), complementing `format: binary`.

Adds regression test `testOpenApi31Completeness` covering all of the above.

Documented limitations (left non-breaking, deferred as larger work):
- multi-type unions still pick the first concrete type (tested behaviour;
  needs a real union type model);
- description/summary/examples propagation (wide blast radius: 51 specs use
  field-level description);
- contains/propertyNames/unevaluated*/dependent*/if-then-else validation
  (needs new validators; parsed-through today);
- info.summary / license.identifier metadata;
- $id/$anchor resolution and $schema/$dynamicRef (ignored non-fatally).

Bumps version 6.4.2 -> 6.5.0 (new features).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@joseegman-idoneea
joseegman-idoneea force-pushed the feat/openapi31-completeness branch from cd17035 to e6cd4c9 Compare July 24, 2026 05:09
Carry property-level `description` and `example` (3.0) / `examples` (3.1, first
entry) into the generated model classes via the @Schema annotation. This also
surfaces the sibling `description` of a `$ref` (OpenAPI 3.1), completing the
earlier $ref+description fix. Values are Java-string-escaped in the template.

- SchemaFieldObject gains `description`/`example`.
- ApiTool.getDescription/getExample (examples[0] fallback).
- ModelBuilder applies them at the property choke point (applyMetadata).
- templateSchema.ftlh emits `description`/`example` on @Schema when present.

Assets across the OpenAPI and AsyncAPI generators are regenerated accordingly.
Note: the Lombok model template does not use @Schema, so descriptions are not
emitted there (unchanged).

Full multiapi-engine suite: 110/110 passing (mvn clean test).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jemacineiras jemacineiras added bug Something isn't working enhancement New feature or request release Adding this tag to a PR will cause a release on merge labels Jul 24, 2026
@jemacineiras
jemacineiras merged commit bcbbd34 into sngular:main Jul 24, 2026
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request release Adding this tag to a PR will cause a release on merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants