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.