This article introduces jSON-schema in plain English, from basic concepts to advanced applications, and analyzes the practical functions of JSON-Schema in combination with practical applications.

One, the origin

What is jSON-schema?

Before we answer that question, let’s look at the background.

With the development of the Internet, the front and back end interaction, from the original text/ HTML, image/* image and other file streams, to the current Application/X-www-form-urlencoded, multipart/form-data, Application/JSON streams, And future Application/OCTEt-stream binaries. However, there is no doubt that the most popular format for front and back end interaction is Application/JSON, and it is also the format that we developers use most in our development process.

In addition, JSON is becoming more and more important in front-end applications. No matter how it develops in the future, it will always play an indispensable role. Why? The author thinks that the most fundamental reason is that it is essentially a object, the object oriented programming bullying today, naturally, the dominance of which cannot be shaken, at the same time it’s lightweight, highly readable, strong extension, high transmission efficiency, also is a kind of important reasons, it is between man and machine interaction plays an important role of media.

As JSON has become more and more widely used, tools related to it have been developed. Json-schema is one of them.

Suppose we have a JSON data format like this:

{
    "id": "1432423230",
    "name": "Jeck",
    "sex": "male"
}
Copy the code

Although the json is straightforward to the developer and we can easily see that it is a string representing a Person, there are still some problems, such as:

  1. Can ID be a number?
  2. Does name have a character limit?
  3. Is sex mandatory? Can it be man and woman?

Maybe as the creator of the project, he knows exactly what these fields mean, but as the project grows, a year later, he may not be able to remember what these fields mean, even as the original developer of the code, let alone the other maintainers who take over the project.

While we all know what meaning the json code (Person), the field inside each Person’s understanding may be different, we can simply according to the attributes the meaning of English to understand the meaning of it, but we can’t assume that everyone’s English level is very high, set of attribute value can make others can see at a glance what meaning.

Therefore, as teams become more and more important today, it is necessary to specify a set of JSON specifications for the team, so that the team has a consistent understanding of it, in order to achieve this goal:

  1. Reduce the cost of understanding;
  2. Improve development efficiency;
  3. Reduce maintenance costs.

So back up, what is jSON-schema again? I’m sure you’re smart enough to have guessed it.

Yes, that’s right, it’s a set of json specifications, and some say it’s a set of validation tools for JSON, a proposed IETF standard… They all mean the same thing.

If you’re familiar with typescript or Flow, you’ll soon be able to work out relationships like this:

Json-schema is to JSON what typescript(or flow) is to javascript

Second, the introduction

1) Basic types

There are two basic types of JSON: Object and ArrayThe value of the value of: string, number, object, array, Boolean, null

Tips: No undefined type

2) Basic concepts

Since it is a set of specifications, there is a lot of semantics, so let’s start with the simplest example, as follows:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/person.schema.json",
  "title": "Person",
  "description": "it is a person object",
  "type": "object",
  "properties": {
    "id": {
      "description": "The unique identifier for a person",
      "type": "string"
    }
  },
  "required": [ "id" ]
}
Copy the code

In general, the formats and properties we see most often are Type and properties, which describe an object, and items, which describe an array.

3) Define attribute values

Id is a unique identifier that describes the person, like our ID number, which is a unique identifier for this piece of data, which is required for the database, and we’re limiting its type to string.

Name is a symbol that describes people, which is closer to human usage. Computers tend to focus on ID, while humans tend to focus on names, so it is usually required and has a maximum length of 50.

Description indicates the description of the field, which makes it clear what the attribute value is intended to say.

Type Specifies the type of the field.

Required is a list of attributes that are required for validation, leaving it blank means no validation, and sudden additions and subtractions of attributes are not validated.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/person.schema.json",
  "title": "Person",
  "description": "it is a person object",
  "type": "object",
  "properties": {
    "id": {
      "description": "The unique identifier for a person",
      "type": "string"
    },
    "name": {
      "description": "The identifier for a person",
      "type": "string",
      "maxLength": 50
    }
  },
  "required": [ "id", "name" ]
}
Copy the code

4) Dig deep into properties

At the same time, we need to standardize gender, otherwise, one person is male and another is man.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/person.schema.json",
  "title": "Person",
  "description": "it is a person object",
  "type": "object",
  "properties": {
    "id": {
      "description": "The unique identifier for a person",
      "type": "string"
    },
    "name": {
      "description": "The identifier for a person",
      "type": "string",
      "maxLength": 50
    },
    "sex": {
      "description": "The gender of the person",
      "type": "string",
      "enum": ["male", "female"]
    },
  },
  "required": [ "id", "name" ]
}
Copy the code

One day, the requirements changed, and the product manager said we need to add another attribute, age, age can not be less than 0, let alone more than 1000 ~

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/person.schema.json",
  "title": "Person",
  "description": "it is a person object",
  "type": "object",
  "properties": {
    "id": {
      "description": "The unique identifier for a person",
      "type": "string"
    },
    "name": {
      "description": "The identifier for a person",
      "type": "string",
      "maxLength": 50
    },
    "sex": {
      "description": "The gender of the person",
      "type": "string",
      "enum": ["male", "female"]
    },
    "age": {
        "description": "The age for a person",
        "type": "number",
        "exclusiveMinimum": 0,
        "maximum": 1000
    }
  },
  "required": [ "id", "name" ]
}
Copy the code

‘exclusiveMinimum’ : ‘greater than’, ‘maximum’ and ‘exclusiveMaximum’ : ‘less than or equal to’

Knowing a person’s name and age seems to be missing something. Imagine if you meet a handsome person or a beautiful woman and you are lucky enough to strike up a conversation and have a good time. What is the last important thing to do before parting?

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/person.schema.json",
  "title": "Person",
  "description": "it is a person object",
  "type": "object",
  "properties": {
    "id": {
      "description": "The unique identifier for a person",
      "type": "string"
    },
    "name": {
      "description": "The identifier for a person",
      "type": "string",
      "maxLength": 50
    },
    "sex": {
      "description": "The gender of the person",
      "type": "string",
      "enum": ["male", "female"]
    },
    "age": {
        "description": "The age for a person",
        "type": "number",
        "exclusiveMinimum": 0,
        "maximum": 1000
    },
    "phone": {
        "description": "The contact for a person",
        "type": "string",
        "pattern": "^[13|14|15|16|17|18|19][0-9]{9}$"
    }
  },
  "required": [ "id", "name" ]
}
Copy the code

String constraints support the description of regular expressions using the pattern keyword.

With the rise of the post-90s and post-00s, they are a group of people with dreams and self-pursuit, so they will pay more and more attention to their own personality and label, but our original project did not have this content field.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/person.schema.json",
  "title": "Person",
  "description": "it is a person object",
  "type": "object",
  "properties": {
    "id": {
      "description": "The unique identifier for a person",
      "type": "string"
    },
    "name": {
      "description": "The identifier for a person",
      "type": "string",
      "maxLength": 50
    },
    "sex": {
      "description": "The gender of the person",
      "type": "string",
      "enum": ["male", "female"]
    },
    "age": {
        "description": "The age for a person",
        "type": "number",
        "exclusiveMinimum": 0,
        "maximum": 1000
    },
    "phone": {
        "description": "The contact for a person",
        "type": "string",
        "pattern": "^[13|14|15|16|17|18|19][0-9]{9}$"
    },
    "tags": {
        "description": "The labels to describe a person",
        "type": "array",
        "items": [
            { "type": "string" }
        ],
        "minItems": 1,
        "uniqueItems": true
    },
  },
  "required": [ "id", "name" ]
}
Copy the code

Introduce items to specify each item in the array, requiring the contents of the array to be of type string. Also, if the field tags are declared, minItems specifies that it has at least one label, and uniqueItems specifies that each label is unique.

5) Nested structure

The data we usually encounter is not flat, the hierarchy is generally relatively deep, here we introduce it to add an address field.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/person.schema.json",
  "title": "Person",
  "description": "it is a person object",
  "type": "object",
  "properties": {
    "id": {
      "description": "The unique identifier for a person",
      "type": "string"
    },
    "name": {
      "description": "The identifier for a person",
      "type": "string",
      "maxLength": 50
    },
    "sex": {
      "description": "The gender of the person",
      "type": "string",
      "enum": ["male", "female"]
    },
    "age": {
        "description": "The age for a person",
        "type": "number",
        "exclusiveMinimum": 0,
        "maximum": 1000
    },
    "phone": {
        "description": "The contact for a person",
        "type": "string",
        "pattern": "^[13|14|15|16|17|18|19][0-9]{9}$"
    },
    "tags": {
        "description": "The labels to describe a person",
        "type": "array",
        "items": [
            { "type": "string" }
        ],
        "minItems": 1,
        "uniqueItems": true
    },
    "address": {
        "description": "The address for a person",
        "type": "object",
        "properties": {
            "country": {
                "type": "string"
            },
            "province": {
                "type": "string"
            },
            "city": {
                "type": "string"
            },
            "region": {
                "type": "string"
            },
            "detail": {
                "type": "string"
            }
        },
        "required": ["country", province", "city", "region"]
    },
  },
  "required": [ "id", "name" ]
}
Copy the code

Finally, let’s take a look at what our JSON definition should look like.

{" id ":" A000000000 ", "name" : "pu yi", "sex", "male", "age" : 112, "phone" : "1300000000", "tags" : [" eat ", "sleeping", "daydream", "the last emperor"], "address" : {" country ":" Chinese ", "province" : "imperial city", "city" : "imperial city", "region" : "dongcheng district", "detail" : "Palace Museum, 4 Jingshan Qianjie ",}Copy the code

For more information about attribute specifications, please go to json-schema.org/draft/2019-…

Advanced usage

1) reuse

From spaceships to mobile phones, many of the world’s most convenient things are created because of laziness. The cute siege lions are also a group of intelligent animals. For many applications we just want to write once, such as the address definition above, there is a scenario where a person can have many different addresses, such as a mailing address and a sending address, which may include school address, business address, home address, rental address and so on. The structure is the same, so it is impossible to define so much address information repeatedly, and jSON-Schema supports this.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
      "address": {
        "type": "object",
        "properties": {
            "country": {
                "type": "string"
            },
            "province": {
                "type": "string"
            },
            "city": {
                "type": "string"
            },
            "region": {
                "type": "string"
            },
            "detail": {
                "type": "string"
            }
        },
        "required": ["country", province", "city", "region"]
    },
  },
  
  "type": "object",
  
  "properties": {
        "receipt_address": {
            "#ref": "#/definitions/address"
        },
        "send_address": {
            "#ref": "#/definitions/address"
        }
  }
}
Copy the code

Or it can be referenced with id and ID and id and ref.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
      "address": {
        "$id": "#address",
        "type": "object",
        "properties": {
            "country": {
                "type": "string"
            },
            "province": {
                "type": "string"
            },
            "city": {
                "type": "string"
            },
            "region": {
                "type": "string"
            },
            "detail": {
                "type": "string"
            }
        },
        "required": ["country", province", "city", "region"]
    },
  },
  
  "type": "object",
  
  "properties": {
        "receipt_address": {
            "#ref": "#address"
        },
        "send_address": {
            "#ref": "#address"
        }
  }
}
Copy the code

2) recursion

$ref = $ref = $ref = $ref = $ref = $ref = $ref yes, we can!

The most common is the HTML DOM structure, which itself generates the DOM recursively, for example:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
      "element": {
        "$id": "#element",
        "type": "object",
        "properties": {
            "name": {
                "type": "string"
            },
            "props": {
                "type": "object",
                "properties": {},
            },
            "children": {
                "type": "array",
                "items": {"$ref": "#element"},
            },
        }
    },
  },
  
  "type": "object",
  
  "properties": {
        "element": {
            "#ref": "#element"
        }
  }
}
Copy the code

It is important to note that a and B do not refer to each other during recursive calls, otherwise an infinite loop will be formed.

Four, practical application

Considering the network bandwidth and development efficiency, we usually omit a lot of practical applications, some of the above description will seem redundant, let’s look at a practical application. In order to@formily/antdAs an example.The jSON-schema corresponding to the above inline layout is:

{ "type": "object", "properties": { "aaa": { "key": "aaa", "name": "aaa", "type": "string", "title": "Field 1", "x - component" : "input"}, "BBB" : {" key ":" BBB ", "name" : "BBB", "type" : "number", "title" : "field 2", "x - component" : "Numberpicker}", "CCC" : {" key ":" CCC ", "name" : "CCC", "type" : "date", "title" : "three fields", "x - component" : "datepicker" } } }Copy the code

The above type specifies what the input value type of the attribute value should be, compared to the jSON-Schema data used for validation.

{
  "type": "object",
  "properties": {
    "aaa": {
      "type": "string",
    },
    "bbb": {
      "type": "number",
    },
    "ccc": {
      "type": "date",
    }
  }
}
Copy the code

Tips: The above “type”:”date” is a new type of draft7.

In the practical application of @formily/ ANTD, the verification attribute and business attribute are mixed together. Strictly speaking, it is not a standard JSON-schema, but a set of its own JSON-schema based on its actual business. You can understand it as pseudo-JSON-schema. But it is worth learning from.

In general, we can also actively verify the validity of json written by using third-party tools such as jsonSchema and React form schema to verify the react-jsonSchema-form.

Five, the summary

Json-schema includes dependencies, additionalItems, Consts, allOf, anyOf, oneOf, Not, if… Then… Else, for more gameplay, go to the JSON-Schema website.

Finally, let’s summarize the basics of JSON-Schema, which is a set of specifications for validating JSON so that both reads and writes follow the same set of rules.

What is a schema?

Wikipedia defines it as:

The word schema comes from The Greek word σχῆμα (SKH ēma), which means shape, or more generally, plan.

Strictly speaking, a schema is a schema or schema. In a database system, it is a structure described by a formal language and a collection of objects.

Xml-schema, YamL-schema… They all refer to a specification and schema for XXX data.

reference

  1. Json-schema is available at json-schema.org/
  2. Xaber.co /2015/10/20/…
  3. @formily/ ANTD SchemaForm: formilyjs.org/#/0yTeT0/jb…

Article | Alan

Pay attention to the object technology, hand in hand to the cloud of technology