Indicative shapes; final key spelling, deserialization details, and dialect deferred to the SIG (#73/#127). RUNTIME validation only — NOT a static matcher.
request:
method: POST
contentType: application/json
# URL/query params — plain JSON Schema over the query slice (default location)
parameterSchema: # a.k.a. query slot; flat top-level props as today
type: object
properties:
promote: { type: boolean }
answerCount: { type: integer }
anyOf: # same-location dep — standard JSON Schema, no unification needed
- not: { required: [promote] }
- required: [answerCount]
# path params — own slot (parsed against the uriTemplate, #127)
pathParamSchema:
type: object
properties: { speakerId: { type: string } }
# headers — own slot; values massaged per #108 registry; tooling MUST lowercase keys (#224)
headerSchema:
type: object
additionalProperties: true # default true so implicit Host/User-Agent don't falsely reject (#224)
properties:
if-match: { type: string }
# cookies — own slot (first-class per #224)
cookieSchema:
type: object
additionalProperties: true
# body — the existing slot, unchanged
contentSchema:
type: object
properties: { id: { type: string } }
A real URL query param literally named body or headers lives at parameterSchema/properties/body — no collision with any region.
request:
# ... per-location slots as above ...
crossDependencies: # OPTIONAL; absent => no cross-type constraint (the common case)
# tooling materializes a synthetic {parameters, headers, body} envelope ONLY to evaluate this
allOf:
# (a) PRESENCE-based cross-type dep — standard JSON Schema 2020-12, works today:
- if: { properties: { parameters: { required: [id] } } }
then: { properties: { body: { required: [id] } } }
# (b) VALUE-EQUALITY cross-type dep (PUT path-ID == body-ID) — the forcing case.
# NOT standard vocab; needs a Relative-JSON-Pointer 'equals' keyword. DEFERRED to #73.
- properties:
body:
properties:
id: { equals: "2/parameters/id" } # relative JSON pointer; vocabulary = #73
query.x vs x deserialization (karenetheridge #100 c5).