1. JSON Schema
JSON Schema 是一種基于 JSON 的格式,用于描述 JSON 資料的結構和驗證 JSON 資料。它為 JSON 資料提供了一個清晰的描述,可以用來驗證、文檔化,以及界定資料的接口。下面是 JSON Schema 的一些核心特點和應用方式的詳細介紹:
- 描述資料格式:使用 JSON Schema,你可以較長的描述 JSON 資料的預期結構,包括哪些字段是必需的,字段的資料類型是什麼(如字元串、數字、布爾值等),以及字段的其他屬性(如字元串的最小長度、最大長度、正規表達式模式等)。
- 資料驗證:JSON Schema 最常見的用途之一是驗證 JSON 資料。這意味着你可以根據定義的 schema 來檢查 JSON 資料是否符合預期的格式,這在處理外部資料或 API 響應時尤其有用。如果資料不符合預期,你可以捕獲這些錯誤并相應地處理它們。
- 自動生成文檔:由于 JSON Schema 以标準化的格式描述了資料的結構,它可以被用來自動生成文檔。這對于 API 的文檔化尤其有用,因為開發者可以清晰地了解 API 接口期望接收什麼樣的資料,以及 API 響應将傳回什麼樣的資料。
- 簡化開發流程:通過使用 JSON Schema 來驗證資料,開發者可以減少手動編寫用于資料驗證的代碼量。這不僅可以提高開發效率,還可以減少由于資料錯誤導緻的 bug。
- 跨語言支援:JSON Schema 有廣泛的程式設計語言支援,包括但不限于 JavaScript、Python、Java 和 C#。這意味着無論你使用什麼程式設計語言,你都可以找到庫來幫助你處理 JSON Schema。
- 版本控制:JSON Schema 本身也在不斷發展,目前有多個版本。每個版本添加了新的功能并對現有功能進行了改進。這使得 JSON Schema 可以适應不斷變化的需求,同時保持向後相容性。
通過使用 JSON Schema,開發者可以建立更加健壯和可靠的應用程式,確定資料的一緻性和準确性,同時提高開發效率和降低維護成本。
2. 誕生背景
JSON Schema 的誕生背景源于對 JSON 資料格式的廣泛采用及随之而來的需要驗證 JSON 資料結構和内容的需求。JSON(JavaScript Object Notation)是一種輕量級的資料交換格式,易于人閱讀和編寫,同時也易于機器解析和生成。随着 Web 服務和應用程式接口(API)的快速發展,JSON 成為了在網絡上進行資料交換的一種流行方式。
在這種背景下,開發者和系統架構師面臨着如何有效驗證 JSON 資料的挑戰,特别是在複雜系統和跨團隊合作中,確定資料的一緻性和正确性變得尤為重要。以下是 JSON Schema 出現的幾個關鍵背景因素:
- 資料驗證需求:随着系統變得越來越依賴于動态和靈活的資料交換,需要一種可靠的方法來驗證資料結構和内容,以防止錯誤資料導緻的問題。
- 自動化和标準化:在自動化處理過程中,如 API 的調用和響應,需要有一個标準方式來描述和驗證資料,進而減少人為幹預和潛在的錯誤。
- 跨語言和跨平台互動:作為一種與語言無關的資料格式,JSON 被廣泛應用于不同程式設計語言和平台之間的互動。JSON Schema 提供了一種統一的方式來定義和驗證資料結構,促進了不同系統之間的互操作性。
- 文檔和協作:JSON Schema 還可以用作文檔,幫助開發者了解資料模型的結構,促進團隊成員之間的溝通和協作。
是以,JSON Schema 應運而生,它不僅解決了資料驗證的問題,還支援文檔生成、自動化測試和開發工具內建等多種用途,成為了現代 Web 開發中不可或缺的一個組成部分。
3. TS vs JSON Schema
JSON Schema 和 TypeScript(TS)都用于確定資料結構的正确性,但它們在應用和目的上存在一些關鍵差別:
- 應用範圍:
- JSON Schema:主要用于描述和驗證 JSON 資料結構,確定 JSON 資料符合預定義的格式。它是獨立于程式設計語言的,可以用于網絡傳輸中的資料驗證、配置檔案的驗證等場景。
- TypeScript:是 JavaScript 的一個超集,它添加了靜态類型定義的功能。TypeScript 主要用于在編譯時檢查代碼中的類型錯誤,提高開發效率和代碼品質。
- 執行時機:
- JSON Schema:通常在運作時用于驗證資料,例如驗證 API 請求/響應的資料結構。
- TypeScript:在編譯時進行類型檢查,編譯後的代碼轉換為普通的 JavaScript,運作時不會進行類型檢查。
- 目的和使用場景:
- JSON Schema:用于確定資料遵守特定的格式和結構,常用于 API 資料交換和配置資料驗證。
- TypeScript:旨在通過引入靜态類型系統來提高代碼的可維護性和可讀性,主要用于開發階段,幫助開發者捕捉類型相關的錯誤。
- 語言和平台:
- JSON Schema:是一個獨立的規範,可以與任何支援 JSON 的程式設計語言一起使用。
- TypeScript:是一種程式設計語言,需要特定的編譯器(TypeScript 編譯器)将 TypeScript 代碼轉換為 JavaScript 代碼。
JSON Schema 主要關注于運作時的資料驗證,確定資料結構的正确性;而 TypeScript 關注于編譯時的類型檢查,提升開發過程中的代碼品質和安全性。兩者雖然在某些方面具有互補性,但服務于程式設計和資料處理的不同階段和方面。
4. 示例
4.1 最小示例
{
"$id": "https://example.com/person.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Person",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "The person's first name."
},
"lastName": {
"type": "string",
"description": "The person's last name."
},
"age": {
"description": "Age in years which must be equal to or greater than zero.",
"type": "integer",
"minimum": 0
}
}
}
資料:
{
"firstName": "John",
"lastName": "Doe",
"age": 21
}
4.2 數組
{
"$id": "https://example.com/arrays.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "A representation of a person, company, organization, or place",
"type": "object",
"properties": {
"fruits": {
"type": "array",
"items": {
"type": "string"
}
},
"vegetables": {
"type": "array",
"items": { "$ref": "#/$defs/veggie" }
}
},
"$defs": {
"veggie": {
"type": "object",
"required": [ "veggieName", "veggieLike" ],
"properties": {
"veggieName": {
"type": "string",
"description": "The name of the vegetable."
},
"veggieLike": {
"type": "boolean",
"description": "Do I like this vegetable?"
}
}
}
}
}
資料:
{
"fruits": [ "apple", "orange", "pear" ],
"vegetables": [
{
"veggieName": "potato",
"veggieLike": true
},
{
"veggieName": "broccoli",
"veggieLike": false
}
]
}
4.3 枚舉
{
"$id": "https://example.com/enumerated-values.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Enumerated Values",
"type": "object",
"properties": {
"data": {
"enum": [42, true, "hello", null, [1, 2, 3]]
}
}
}
資料:
{
"data": [1, 2, 3]
}
4.4 正則
{
"$id": "https://example.com/regex-pattern.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Regular Expression Pattern",
"type": "object",
"properties": {
"code": {
"type": "string",
"pattern": "^[A-Z]{3}-\\d{3}#34;
}
}
}
資料:
{
"code": "ABC-123"
}
4.5 嵌套
{
"$id": "https://example.com/complex-object.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Complex Object",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer",
"minimum": 0
},
"address": {
"type": "object",
"properties": {
"street": {
"type": "string"
},
"city": {
"type": "string"
},
"state": {
"type": "string"
},
"postalCode": {
"type": "string",
"pattern": "\\d{5}"
}
},
"required": ["street", "city", "state", "postalCode"]
},
"hobbies": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["name", "age"]
}
資料:
{
"name": "John Doe",
"age": 25,
"address": {
"street": "123 Main St",
"city": "New York",
"state": "NY",
"postalCode": "10001"
},
"hobbies": ["reading", "running"]
}
4.6 條件驗證
{
"$id": "https://example.com/conditional-validation-dependentRequired.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Conditional Validation with dependentRequired",
"type": "object",
"properties": {
"foo": {
"type": "boolean"
},
"bar": {
"type": "string"
}
},
"dependentRequired": {
"foo": ["bar"]
}
}
{
"$id": "https://example.com/conditional-validation-dependentSchemas.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Conditional Validation with dependentSchemas",
"type": "object",
"properties": {
"foo": {
"type": "boolean"
},
"propertiesCount": {
"type": "integer",
"minimum": 0
}
},
"dependentSchemas": {
"foo": {
"required": ["propertiesCount"],
"properties": {
"propertiesCount": {
"minimum": 7
}
}
}
}
}
{
"$id": "https://example.com/conditional-validation-if-else.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Conditional Validation with If-Else",
"type": "object",
"properties": {
"isMember": {
"type": "boolean"
},
"membershipNumber": {
"type": "string"
}
},
"required": ["isMember"],
"if": {
"properties": {
"isMember": {
"const": true
}
}
},
"then": {
"properties": {
"membershipNumber": {
"type": "string",
"minLength": 10,
"maxLength": 10
}
}
},
"else": {
"properties": {
"membershipNumber": {
"type": "string",
"minLength": 15
}
}
}
}
5. 驗證器
JS 可使用 ajv:
// or ESM/TypeScript import
import Ajv from "ajv";
// Node.js require:
const Ajv = require("ajv");
const ajv = new Ajv(); // options can be passed, e.g. {allErrors: true}
const schema = {
type: "object",
properties: {
foo: { type: "integer" },
bar: { type: "string" },
},
required: ["foo"],
additionalProperties: false,
};
const data = {
foo: 1,
bar: "abc",
};
const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) console.log(validate.errors);
其他平台可參考官網:
來源-微信公衆号:好朋友樂平
出處:https://mp.weixin.qq.com/s/G8RdfUpUjTYWtsFHdLIniw