|
1 | 1 | --- |
2 | 2 | title: Extending Closed Schemas with unevaluatedProperties |
3 | | -description: "Learn how to extend closed schemas in JSON Schema objects using the unevaluatedProperties keyword to allow additional properties, overcoming the limitations of additionalProperties in subschemas." |
4 | | -keywords: "extending closed schemas, unevaluatedProperties, JSON Schema, JSON Schema objects, additionalProperties, subschemas, allOf, combining keywords" |
| 3 | +description: "Learn how to extend closed schemas in JSON Schema using the unevaluatedProperties keyword with $ref, enabling safe schema composition while maintaining type safety." |
| 4 | +keywords: "extending closed schemas, unevaluatedProperties, JSON Schema, $ref, $defs, additionalProperties, subschemas, schema composition" |
5 | 5 | --- |
6 | 6 |
|
7 | | - |
8 | 7 | # Extending Closed Schemas |
9 | 8 |
|
10 | | -Previously in the Objects module, we learned to `additionalProperties`. However, it is important to note that `additionalProperties` only recognizes properties declared in the same [subschema](https://json-schema.org/learn/glossary#subschema) as itself. |
| 9 | +Previously in the Objects , we learned about `additionalProperties`. However, it is important to note that `additionalProperties` only recognizes properties declared in the same [subschema](https://json-schema.org/learn/glossary#subschema) as itself. |
| 10 | + |
| 11 | +So, `additionalProperties` can restrict you from "extending" a schema using combining keywords such as `$ref`. In the following example, we can see how the `additionalProperties` can cause attempts to extend the address schema example to fail. |
11 | 12 |
|
12 | | -So, `additionalProperties` can restrict you from "extending" a schema using combining [keywords](https://json-schema.org/learn/glossary#subschema) such as `allOf`. In the following example, we can see how the `additionalProperties` can cause attempts to extend the address schema example to fail. |
| 13 | +## The Problem with `additionalProperties` |
13 | 14 |
|
14 | | -```json highlightLineStart={11} |
| 15 | +Let's say we have a reusable address schema in `$defs` that we want to extend. If we try to use `additionalProperties` to keep it closed, we run into issues: |
| 16 | +```json highlightLineStart={6} |
15 | 17 | { |
16 | | - "allOf": [ |
17 | | - { |
| 18 | + "$ref": "#/$defs/address", |
| 19 | + "properties": { |
| 20 | + "type": { "enum": ["residential", "business"] } |
| 21 | + }, |
| 22 | + "additionalProperties": false, |
| 23 | + "required": ["type"], |
| 24 | + "$defs": { |
| 25 | + "address": { |
18 | 26 | "type": "object", |
19 | 27 | "properties": { |
20 | 28 | "street_address": { "type": "string" }, |
21 | 29 | "city": { "type": "string" }, |
22 | 30 | "state": { "type": "string" } |
23 | 31 | }, |
24 | | - "required": ["street_address", "city", "state"], |
25 | | - "additionalProperties": false |
| 32 | + "required": ["street_address", "city", "state"] |
26 | 33 | } |
27 | | - ], |
28 | | - "properties": { |
29 | | - "type": { "enum": [ "residential", "business" ] } |
30 | | - }, |
31 | | - "required": ["type"] |
| 34 | + } |
32 | 35 | } |
33 | 36 | ``` |
34 | | -The above [schema](https://json-schema.org/learn/glossary#schema) will not allow you to define `type` property. because `additionalProperties` is set to `false`. The reason is, `additionalProperties` only recognizes properties declared in the same [subschema](https://json-schema.org/learn/glossary#subschema). |
35 | 37 |
|
| 38 | +This [schema](https://json-schema.org/learn/glossary#schema) will **reject valid data** because `additionalProperties: false` only sees the `type` property defined locally. It doesn't recognize the properties from the referenced schema (`street_address`, `city`, `state`), so it would incorrectly treat them as "additional" properties and reject them. |
36 | 39 |
|
37 | 40 | ## Unevaluated Properties |
38 | 41 |
|
39 | | -The challenge we saw with `additionalProperties` can be solved using the `unevaluatedProperties` keyword. This keyword allows you to define properties that are not evaluated by the current schema. |
| 42 | +The challenge we saw with `additionalProperties` can be solved using the `unevaluatedProperties` keyword. This keyword allows you to define properties that are not evaluated by the current schema. |
40 | 43 |
|
41 | | -```json highlightLineStart={15} |
| 44 | +```json highlightLineStart={6} |
42 | 45 | { |
43 | | - "allOf": [ |
44 | | - { |
| 46 | + "$ref": "#/$defs/address", |
| 47 | + "properties": { |
| 48 | + "type": { "enum": ["residential", "business"] } |
| 49 | + }, |
| 50 | + "unevaluatedProperties": false, |
| 51 | + "required": ["type"], |
| 52 | + "$defs": { |
| 53 | + "address": { |
45 | 54 | "type": "object", |
46 | 55 | "properties": { |
47 | 56 | "street_address": { "type": "string" }, |
48 | 57 | "city": { "type": "string" }, |
49 | 58 | "state": { "type": "string" } |
50 | 59 | }, |
51 | | - "required": ["street_address", "city", "state"], } |
52 | | - ], |
53 | | - "properties": { |
54 | | - "type": { "enum": [ "residential", "business" ] } |
55 | | - }, |
56 | | - "unevaluatedProperties": false, |
57 | | - "required": ["type"] |
| 60 | + "required": ["street_address", "city", "state"] |
| 61 | + } |
| 62 | + } |
58 | 63 | } |
59 | 64 | ``` |
60 | 65 |
|
|
0 commit comments