+ );
+ },
+ },
+
a: {
component: ({ children, href, title, className }) => {
if (!href) return children;
@@ -665,6 +675,7 @@ export function TableOfContentMarkdown({
'figure',
'Bigquote',
'Regularquote',
+ 'specialBox',
),
},
}}
diff --git a/pages/blog/posts/applicability-json-schema-fundamentals-part-1.md b/pages/blog/posts/applicability-json-schema-fundamentals-part-1.md
index ece4b13ae..d83c61260 100644
--- a/pages/blog/posts/applicability-json-schema-fundamentals-part-1.md
+++ b/pages/blog/posts/applicability-json-schema-fundamentals-part-1.md
@@ -1,6 +1,6 @@
---
-title: "It all starts with applicability - JSON Schema Fundamentals part 1"
-date: "2022-03-21"
+title: 'It all starts with applicability - JSON Schema Fundamentals part 1'
+date: '2022-03-21'
tags:
- Fundamentals
type: Engineering
@@ -10,14 +10,13 @@ authors:
photo: /img/avatars/benhutton.webp
link: https://www.x.com/relequestual
byline: JSON Schema Specification Lead @Postman
-excerpt: "We explore the fundamental JSON Schema concepts: Applicability, Subschemas, and Assertion Boolean Logic - Everyone needs good fundamentals."
+excerpt: 'We explore the fundamental JSON Schema concepts: Applicability, Subschemas, and Assertion Boolean Logic - Everyone needs good fundamentals.'
---
"Validation begins by applying the root Schema to the complete instance document. Applicator keywords apply subschemas to the instance location." - Borrowed from [JSON Schema in 5 minutes](https://json-schema.org/blog/posts/json-schema-in-5-minutes).
The primary use case for JSON Schema is validation. Therefore it's imperative to understand precisely how the validation process happens. Let's take a little time to properly grasp the fundamental JSON Schema concept of Applicability.
-
# Applicator keywords
JSON Schema consists of many keywords. These keywords can be broken down into categories, one of which is "applicator". In the physical sense, an "applicator" is a thing you use to introduce one substance to another. For example, a cloth might be used to introduce polish to a nice wooden table. The cloth is the applicator. The polish is applied to the table via the cloth.
@@ -30,23 +29,21 @@ The validation process for JSON Schema begins with applying the whole JSON Schem
A JSON Schema may be a Boolean or an Object. In the introductory article mentioned above, we noted how a Boolean Schema of `true` or `false` resulted in the same assertion result (true and false respectivly) regardless of the instance data. We also noted how the equivalent Object Schemas were `{ }` and `{ "not": { } }` respectively. (The `not` keyword inverts the assertion result.)
-
+
Vocabulary check
An "assertion" is a statement of fact. This is used in reference to the result of testing in Computing. The test might be called "X is 1". If the test passes, the assertion is true!
-
+
When we talk about the whole Schema in terms of application, we usually refer to it as the "root Schema". This is because the other Schemas which are applied to specific instance locations are different, and we call them "subschemas". Differentiating between the root Schema and subschemas allows us to communicate with clarity which JSON Schema we're talking about, and when to use the Schema as part of the validation process.
-
+
The following examples assume to be using JSON Schema 2020-12. Where there are things you should know about previous versions (or drafts) of JSON Schema, it will be highlighted.
-
-
+
# Subschema application - Validating Objects and Arrays
If your JSON instance is an Object or an Array, you'll likely want to validate the values of the Object or the items in the Array. In this introduction, you'll be using the `properties` and `items` keywords, and subschemas.
-
## Validating Objects
Let's jump into an example. Here's our instance data.
@@ -85,6 +82,8 @@ OK, let's check our Schema does all we need it to. What happens when our instanc
"isEmailConfirmed": "true"
}
// isEmailConfirmed should be a Boolean, not a string.
+
+
// Will cause validation error.
```
@@ -98,7 +97,7 @@ We need to make sure we define the appropriate constraint if we want any keys to
"email": { "type": "string" },
"isEmailConfirmed": { "type": "boolean" }
},
- "required": [ "id", "name", "email" ]
+ "required": ["id", "name", "email"]
}
```
@@ -112,6 +111,8 @@ We can now be confident that if our required fields are missing, validation will
"isEmaleConfirmed": "true"
}
// Typo for key "isEmaleConfirmed".
+
+
// Validates because of applicability.
```
@@ -127,16 +128,16 @@ Luckily, picking this up with our Schema is simple. The `additionalProperties` k
"email": { "type": "string" },
"isEmailConfirmed": { "type": "boolean" }
},
- "required": [ "id", "name", "email" ],
+ "required": ["id", "name", "email"],
"additionalProperties": false
}
```
The value of `additionalProperties` is not just a Boolean, but a Schema. This subschema value is applied to all values of the instance object that are not defined in the `properties` object in our example. You could use `additionalProperties` to allow additional properties, but constrain their values to be a String.
-
+
There is a little simplification here to help us understand the concept we're looking to learn. If you want to dig a little deeper, check out our learning resources on `additionalProperties`.
-
+
Finally, what if we expect an Object, but are given an Array or another non-object type?
@@ -149,6 +150,8 @@ Finally, what if we expect an Object, but are given an Array or another non-obje
"isEmaleConfirmed": "true"
}
]
+
+
// An array is not an object...
```
@@ -165,7 +168,7 @@ The three keywords we've explored so far, `properties`, `required`, and `additio
"email": { "type": "string" },
"isEmailConfirmed": { "type": "boolean" }
},
- "required": [ "id", "name", "email" ],
+ "required": ["id", "name", "email"],
"additionalProperties": false
}
```
@@ -174,12 +177,11 @@ In summary, for the soundest validation, we must express all the constraints we
Note, `type` takes an Array of types. It may be that your instance is allowed to be an Object or an Array, and constraints for both can be defined within the same Schema Object.
-
## Validating Arrays
-
+
In this introduction, we're only going to be covering how things work for JSON Schema 2020-12. If you're using a previous version, including "draft-7" or prior, you will likely benefit from digging a little deeper into the learning resources for Array validation.
-
+
Let's step back to our previous example data, where we were provided with an Array as opposed to an Object. Let's say our data is now only allowed to be an Array.
@@ -195,7 +197,7 @@ To validate every item in the array, we need to use the `items` keyword. The `it
"email": { "type": "string" },
"isEmailConfirmed": { "type": "boolean" }
},
- "required": [ "id", "name", "email" ],
+ "required": ["id", "name", "email"],
"additionalProperties": false
}
}
@@ -205,7 +207,6 @@ As with the applicability rules of `properties`, the value Schema of `items` is
There are other keywords that are applicable to arrays, but If I continue to explain all of them in detail, this article might start to turn into a reference book! Moving on...
-
# Apply but modify - Boolean logic with subschemas
JSON Schema applicator keywords can do more than just apply a subschema and take the resulting Boolean assertion. Applicator keywords can conditionally apply subschemas, and combine or modify any resulting assertions using boolean logic.
@@ -222,18 +223,19 @@ This sounds simple, but let's look at some examples.
```json caption="allOf/example1.schema.json"
{
- "allOf": [ true, true, true]
+ "allOf": [true, true, true]
}
```
```json caption="allOf/example2.schema.json"
{
- "allOf": [ true, false, true]
+ "allOf": [true, false, true]
}
```
-
+
+
Remember: A Boolean is a valid schema that always produces the assertion result of its value, regardless of the instance data.
-
+
Our first "allOf" example shows the array having three subschemas, which are all `true`. The results are combined using the boolean logic AND operator. The resulting assertion from the `allOf` keyword is `true`.
@@ -243,16 +245,15 @@ The `true` and `false` Boolean Schemas in this example could be any subschemas t
Let's take the two examples again, but use `anyOf` rather than `allOf`.
-
```json caption="anyOf/example1.schema.json"
{
- "anyOf": [ true, true, true]
+ "anyOf": [true, true, true]
}
```
```json caption="anyOf/example2.schema.json"
{
- "anyOf": [ true, false, true]
+ "anyOf": [true, false, true]
}
```
@@ -329,7 +330,8 @@ Let's go back to our array of people data, modify it, and say it represents an a
"email": "bob@example.com",
"isStudent": true,
"year": 1
- }, {
+ },
+ {
"name": "Alice",
"email": "alice@example.com",
"isTeacher": true,
@@ -343,7 +345,7 @@ To start, let's do the same as we did when creating our first schema. Copy the i
```json caption="oneOf/example1.schema.json"
{
"items": {
- "oneOf":[
+ "oneOf": [
{
"properties": {
"name": { "type": "string" },
@@ -351,7 +353,8 @@ To start, let's do the same as we did when creating our first schema. Copy the i
"isStudent": { "type": "boolean" },
"year": { "type": "number" }
}
- }, {
+ },
+ {
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
@@ -376,7 +379,7 @@ Yikes! That's not what we want!
But why isn't it working? Why isn't the instance passing validation?
-__What do we know?__
+**What do we know?**
The validator is "failing fast". This means it's stopping after the first error.
@@ -430,4 +433,4 @@ All feedback is welcome. If you have questions or comments, you can find me on t
- [JSON Schema live playground (hyperjump validator) for all drafts (from draft-04)](https://json-schema.hyperjump.io)
- [Links to RFC specification documents](/specification)
-Photo by Heidi Fin on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
\ No newline at end of file
+Photo by Heidi Fin on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)