fix(schema): use patternProperties as map value type#3024
Open
schani wants to merge 8 commits into
Open
Conversation
Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
…ed map) The pattern-properties-map.schema fixture's a1 uses additionalProperties: true, which quicktype models as a map with an any-typed value. cjson does not support the pure Any type (see the existing any.schema / optional-any.schema skips), so it drops arbitrary map entries on round-trip. Scope the fixture out for cjson, matching the existing documented limitation. Co-Authored-By: Claude <noreply@anthropic.com>
…imitation (#3024) Kotlin (Klaxon and Jackson) coerces the wrong-typed map value in pattern-properties-map.1.fail.json's "team": 42 instead of rejecting it, so the fail sample doesn't fail as expected. Add the schema to the existing skipsMapValueValidation list, the same documented remedy already used for go-schema-pattern-properties.schema and unevaluated-properties.schema. Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
… backends The bare `.fail.json` sample put a number where a string-typed map value was expected. Many backends (Java/Jackson, C#, Kotlin, Rust, Python, etc.) leniently coerce a JSON number into a string when deserializing a `map<string, string>`, so the sample did not make the generated program exit nonzero and the "Expected failure" assertion failed across those languages. Mirror the proven `go-schema-pattern-properties` design instead: add an integer-typed pattern-properties map (`a3`) and drive the negative case with a string where an integer is expected. Non-numeric-to-integer coercion is reliably rejected by every backend that validates map values, and the few that do not validate map values at all already skip this schema via `skipsMapValueValidation`. The faithful `a1` (any-valued) and `a2` (string-valued) maps from issue #1549 are kept as-is. Co-Authored-By: Claude <noreply@anthropic.com>
Generated-output differences23 files differ — 0 modified, 23 new, 0 deleted |
Generated-output differences24 files differ — 0 modified, 24 new, 0 deleted |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
An object schema with
additionalProperties: false(or unset) pluspatternPropertieswas ignored entirely, so quicktype generated an emptyinterface/class for that object instead of a map keyed by the pattern's
value type.
Minimal repro (from the issue,
--src-lang schema --lang ts):Before:
After:
Same fix applies to C# (
a2now generatesDictionary<string, string>instead of an empty class).
Root cause
packages/quicktype-core/src/input/JSONSchemaInput.tsonly ever looked atpatternProperties["*"](a narrow hack originally added for issue #976) andonly when
additionalPropertieswasundefined. Any other pattern key, oran explicit
additionalProperties: false, meantpatternPropertieswassilently dropped, producing an object with no properties and no map type.
Fix
When
additionalPropertiesis nottrue(quicktype can't representper-pattern keys, so it approximates all matching properties with a map
type), collect the schemas of all
patternPropertiesentries — plus anyschema-valued
additionalProperties— and use them as the object'sadditional-properties (map value) type; combine multiple schemas with
anyOf. Also addedschema.patternProperties !== undefinedto the set ofschema fields that mark a JSON Schema node as needing type expansion, so
patternProperties-only nodes aren't skipped.Test coverage
Added an end-to-end JSON Schema fixture:
test/inputs/schema/pattern-properties-map.schematest/inputs/schema/pattern-properties-map.1.jsonreproducing the issue's
a1/a2example (additionalProperties: trueandadditionalProperties: false, both withpatternProperties). This isauto-discovered by the existing schema-fixture harness across all
languages that run schema fixtures.
Verification
npm run buildpasses.npx vitest run test/unit— 169/169 passing.FIXTURE=schema-typescript script/test— 71/71 passing, including thenew
pattern-properties-map.schemafixture and the pre-existinggo-schema-pattern-properties.schemafixture (confirming issue Infer property type based on patternProperties if pattern is .* #976'soriginal scenario still works).
--lang tsand--lang csandconfirmed both now emit a map type instead of an empty
interface/class.
schema-csharpfixture was not run locally (nodotnettoolchain inthis environment); CI will validate it.
Fixes #1549
🤖 Generated with Claude Code