Skip to content

feat(jsonschemagen): emit propertyNames from inlined-dict key slot constraints#16

Open
jdsika wants to merge 1 commit into
mainfrom
feat/jsonschemagen-propertynames-from-key-pattern
Open

feat(jsonschemagen): emit propertyNames from inlined-dict key slot constraints#16
jdsika wants to merge 1 commit into
mainfrom
feat/jsonschemagen-propertynames-from-key-pattern

Conversation

@jdsika

@jdsika jdsika commented Jun 18, 2026

Copy link
Copy Markdown

Summary

For an inlined-as-dict slot (inlined: true, inlined_as_list: false) whose range
class has an identifier/key slot, render the key slot's string-applicable
constraints
onto JSON Schema propertyNames. Previously these were silently
dropped, leaving the generated schema strictly looser than the model declares.

Motivation (standards)

Grounded at both ends:

  • LinkML inlining semantics (https://linkml.io/linkml/schemas/inlining.html) — in
    the inlined-dict form the dictionary key is the identifier value of the range
    class (not repeated in the value object: "it is acting as a key for that object, it
    doesn't need to be included"). So constraints on the identifier/key slot are, by
    LinkML's serialization, constraints on the keys.
  • JSON Schema Core, draft 2019-09, §9.3.2.5 (propertyNames, Applicator
    vocabulary)
    — the subschema is applied to each property name, which "will always
    be a string." propertyNames composes conjunctively with the existing
    additionalProperties value schema.

Changes

  • Derive the key constraints from the key slot via the existing
    get_value_constraints_for_slot helper, then emit the string-applicable subset
    onto propertyNames: pattern, enum (equals_string_in), and a string
    const (equals_string).
  • Numeric constraints are intentionally excluded because property names are always
    strings: minimum/maximum are no-ops on strings, and a numeric const
    (equals_number) would reject every key. allOf (from range_expression) is
    likewise not emitted onto keys.
  • structured_pattern is honored when materialize_patterns is enabled, identical to
    how value patterns are handled (documented in-code).
  • Backward compatible: propertyNames is emitted only when a string-applicable key
    constraint applies.

Notes

  • propertyNames is available since draft-06; the generator emits draft 2019-09.
  • Regex dialect (ECMA-262) is consistent with the generator's existing pattern
    emission.

Test

Parametrized over identifier/key key slots; covers literal pattern,
equals_string_in (enum), string equals_string (const), structured_pattern
(with/without materialization), and behavioral validate good/bad-key checks. Negative
controls assert that a numeric const and numeric minimum/maximum produce no
propertyNames (so numeric-string keys are not wrongly rejected), and that an
unconstrained key slot is unchanged.

@jdsika jdsika force-pushed the feat/jsonschemagen-propertynames-from-key-pattern branch from 8a292b2 to 29f18b0 Compare June 18, 2026 08:25
@jdsika jdsika changed the title feat(jsonschemagen): emit propertyNames from inlined-dict key slot pattern feat(jsonschemagen): emit propertyNames from inlined-dict key slot constraints Jun 18, 2026
@jdsika jdsika force-pushed the feat/jsonschemagen-propertynames-from-key-pattern branch from 29f18b0 to 908094b Compare June 18, 2026 13:34
…nstraints

For an inlined-as-dict slot whose range class has an identifier/key slot, render the
key slot's string-applicable constraints onto JSON Schema propertyNames (draft-06+)
instead of dropping them. In the inlined-dict form the mapping key is the identifier
value, so the key slot's constraints constrain the keys. JSON object keys are always
strings, so only pattern, enum (equals_string_in) and a string const (equals_string)
are emitted; numeric minimum/maximum, numeric const (equals_number) and allOf are
excluded -- a numeric const would otherwise reject every key. structured_pattern is
honored when materialize_patterns is enabled, consistent with value patterns.
Backward compatible: emitted only when a string-applicable key constraint applies.

Signed-off-by: jdsika <carlo.van-driesten@vdl.digital>
@jdsika jdsika force-pushed the feat/jsonschemagen-propertynames-from-key-pattern branch from 908094b to b49cce8 Compare June 18, 2026 13:45
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.

1 participant