天天看點

告别繁瑣的資料校驗:用JSON Schema簡化你的代碼

作者:閃念基因
告别繁瑣的資料校驗:用JSON Schema簡化你的代碼

1. JSON Schema

JSON Schema 是一種基于 JSON 的格式,用于描述 JSON 資料的結構和驗證 JSON 資料。它為 JSON 資料提供了一個清晰的描述,可以用來驗證、文檔化,以及界定資料的接口。下面是 JSON Schema 的一些核心特點和應用方式的詳細介紹:

  1. 描述資料格式:使用 JSON Schema,你可以較長的描述 JSON 資料的預期結構,包括哪些字段是必需的,字段的資料類型是什麼(如字元串、數字、布爾值等),以及字段的其他屬性(如字元串的最小長度、最大長度、正規表達式模式等)。
  2. 資料驗證:JSON Schema 最常見的用途之一是驗證 JSON 資料。這意味着你可以根據定義的 schema 來檢查 JSON 資料是否符合預期的格式,這在處理外部資料或 API 響應時尤其有用。如果資料不符合預期,你可以捕獲這些錯誤并相應地處理它們。
  3. 自動生成文檔:由于 JSON Schema 以标準化的格式描述了資料的結構,它可以被用來自動生成文檔。這對于 API 的文檔化尤其有用,因為開發者可以清晰地了解 API 接口期望接收什麼樣的資料,以及 API 響應将傳回什麼樣的資料。
  4. 簡化開發流程:通過使用 JSON Schema 來驗證資料,開發者可以減少手動編寫用于資料驗證的代碼量。這不僅可以提高開發效率,還可以減少由于資料錯誤導緻的 bug。
  5. 跨語言支援:JSON Schema 有廣泛的程式設計語言支援,包括但不限于 JavaScript、Python、Java 和 C#。這意味着無論你使用什麼程式設計語言,你都可以找到庫來幫助你處理 JSON Schema。
  6. 版本控制:JSON Schema 本身也在不斷發展,目前有多個版本。每個版本添加了新的功能并對現有功能進行了改進。這使得 JSON Schema 可以适應不斷變化的需求,同時保持向後相容性。

通過使用 JSON Schema,開發者可以建立更加健壯和可靠的應用程式,確定資料的一緻性和準确性,同時提高開發效率和降低維護成本。

2. 誕生背景

JSON Schema 的誕生背景源于對 JSON 資料格式的廣泛采用及随之而來的需要驗證 JSON 資料結構和内容的需求。JSON(JavaScript Object Notation)是一種輕量級的資料交換格式,易于人閱讀和編寫,同時也易于機器解析和生成。随着 Web 服務和應用程式接口(API)的快速發展,JSON 成為了在網絡上進行資料交換的一種流行方式。

在這種背景下,開發者和系統架構師面臨着如何有效驗證 JSON 資料的挑戰,特别是在複雜系統和跨團隊合作中,確定資料的一緻性和正确性變得尤為重要。以下是 JSON Schema 出現的幾個關鍵背景因素:

  1. 資料驗證需求:随着系統變得越來越依賴于動态和靈活的資料交換,需要一種可靠的方法來驗證資料結構和内容,以防止錯誤資料導緻的問題。
  2. 自動化和标準化:在自動化處理過程中,如 API 的調用和響應,需要有一個标準方式來描述和驗證資料,進而減少人為幹預和潛在的錯誤。
  3. 跨語言和跨平台互動:作為一種與語言無關的資料格式,JSON 被廣泛應用于不同程式設計語言和平台之間的互動。JSON Schema 提供了一種統一的方式來定義和驗證資料結構,促進了不同系統之間的互操作性。
  4. 文檔和協作:JSON Schema 還可以用作文檔,幫助開發者了解資料模型的結構,促進團隊成員之間的溝通和協作。

是以,JSON Schema 應運而生,它不僅解決了資料驗證的問題,還支援文檔生成、自動化測試和開發工具內建等多種用途,成為了現代 Web 開發中不可或缺的一個組成部分。

3. TS vs JSON Schema

JSON Schema 和 TypeScript(TS)都用于確定資料結構的正确性,但它們在應用和目的上存在一些關鍵差別:

  1. 應用範圍:
  2. JSON Schema:主要用于描述和驗證 JSON 資料結構,確定 JSON 資料符合預定義的格式。它是獨立于程式設計語言的,可以用于網絡傳輸中的資料驗證、配置檔案的驗證等場景。
  3. TypeScript:是 JavaScript 的一個超集,它添加了靜态類型定義的功能。TypeScript 主要用于在編譯時檢查代碼中的類型錯誤,提高開發效率和代碼品質。
  4. 執行時機:
  5. JSON Schema:通常在運作時用于驗證資料,例如驗證 API 請求/響應的資料結構。
  6. TypeScript:在編譯時進行類型檢查,編譯後的代碼轉換為普通的 JavaScript,運作時不會進行類型檢查。
  7. 目的和使用場景:
  8. JSON Schema:用于確定資料遵守特定的格式和結構,常用于 API 資料交換和配置資料驗證。
  9. TypeScript:旨在通過引入靜态類型系統來提高代碼的可維護性和可讀性,主要用于開發階段,幫助開發者捕捉類型相關的錯誤。
  10. 語言和平台:
  11. JSON Schema:是一個獨立的規範,可以與任何支援 JSON 的程式設計語言一起使用。
  12. 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:

告别繁瑣的資料校驗:用JSON Schema簡化你的代碼
// 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);
           

其他平台可參考官網:

告别繁瑣的資料校驗:用JSON Schema簡化你的代碼

來源-微信公衆号:好朋友樂平

出處:https://mp.weixin.qq.com/s/G8RdfUpUjTYWtsFHdLIniw