Specification scope: Core with the Validation companion specification.
A regular expression over member names can answer two different questions: which value schema applies here, and is this name allowed at all?
JSON Structure keeps those questions separate. It also keeps objects and maps
separate, so the vocabulary has parallel names: patternProperties for object
properties and patternKeys for map entries.
Objects have declared structure
Suppose a telemetry envelope has fixed members plus vendor extension fields.
Every extension begins with x- and carries a string value.
{
"$schema": "https://json-structure.org/meta/validation/v0/#",
"$id": "https://schemas.example.com/telemetry-envelope",
"name": "TelemetryEnvelope",
"type": "object",
"properties": {
"deviceId": { "type": "string" },
"timestamp": { "type": "datetime" },
"labels": {
"type": "map",
"values": { "type": "string" },
"patternKeys": {
"^[a-z][a-z0-9_.-]{0,31}$": { "type": "string", "maxLength": 64 }
},
"keyNames": {
"type": "string",
"pattern": "^[a-z][a-z0-9_.-]{0,31}$"
}
}
},
"required": ["deviceId", "timestamp", "labels"],
"patternProperties": {
"^x-[a-z][a-z0-9-]*$": { "type": "string", "maxLength": 128 }
},
"propertyNames": {
"type": "string",
"pattern": "^(deviceId|timestamp|labels|x-[a-z][a-z0-9-]*)$"
},
"additionalProperties": true
}
This instance mixes the stable envelope with one extension and three dynamic labels:
{
"deviceId": "pump-17",
"timestamp": "2026-11-02T08:15:00Z",
"labels": {
"site": "west",
"line.id": "L4",
"maintenance-window": "night"
},
"x-contoso-firmware": "4.8.2"
}
patternProperties does not declare an object property. It finds properties
whose names match the expression and validates their values against the paired
schema. Declared members still come from properties.
Maps have entries, not ad hoc properties
The labels member is a map because its keys are data. There is no finite
catalog of label names. values gives every entry a string type, while
patternKeys applies a more specific value constraint when a key matches its
expression.
In this example every permitted key matches, so patternKeys repeats the
string type and adds maxLength. That repetition is intentional: the keyword
selects values by key pattern; it does not decide which keys may exist.
When several patterns match one name, every corresponding value schema applies. The effects combine with logical AND. Pattern order has no precedence semantics.
Name schemas answer the other question
propertyNames evaluates every object property name as a string instance. Here
it admits the three declared names and the x- extension convention, excluding
unrecognized object members even though additionalProperties is true.
keyNames performs the equivalent job for every map key. A label named
Region/Zone fails because the slash and uppercase letters violate the key
schema, regardless of whether its value is a perfectly good string.
patternProperties and patternKeys choose value constraints based on names.
propertyNames and keyNames validate the names themselves. If you use only
the first pair, a schema can check the associated values and still accept a
misspelled or unexpected key.
The draft requires ECMAScript 2022 regular-expression syntax and warns about regular expression denial-of-service (ReDoS) attacks. JSON Structure Core also constrains identifiers, so regexes do not grant names that core syntax otherwise forbids.
The meta-schema omits four pattern keywords
The validation draft names its opt-in JSONSchemaValidation; the extended
meta-schema offers JSONStructureValidation. As checked on 25 August 2026,
meta/extended/v0/index.json omits all four keywords used here: patternProperties, patternKeys,
propertyNames, and keyNames.
The example therefore uses the repository’s validation meta-schema URI and the
keywords as defined by the draft. A draft-aware processor can evaluate them;
the current meta-schema cannot validate this schema document completely.
Modeling labels as an object would evade that tooling gap by changing the
data model, which would be the wrong fix.