JSON Schema
data/ 中的每个文件在 schema/ 中都有对应的 JSON Schema(draft-07)。这些 schema 由 TypeScript 类型生成,因此类型、schema 和数据三者不会互相脱节:只要其中任意两者不一致,CI 就会失败。
| 数据文件 | Schema |
|---|---|
data/judicial-areas.json | judicial-areas.schema.json |
data/arrondissements.json | arrondissements.schema.json |
data/cantons.json | cantons.schema.json |
data/canton-boundaries.json | canton-boundaries.schema.json |
data/municipalities.json | municipalities.schema.json |
data/regions.json | regions.schema.json |
data/provinces.json | provinces.schema.json |
data/courts.json | courts.schema.json |
data/prisons.json | prisons.schema.json |
data/houses-of-justice.json | houses-of-justice.schema.json |
data/postal-codes.json | postal-codes.schema.json |
data/interest-rates.json | interest-rates.schema.json |
每个 schema 的 $id 就是它在本网站上的 URL,例如 https://pieterjanscheir.github.io/belgica/schema/courts.schema.json。npm 包中也包含它们,路径为 belgica/schema/courts.schema.json。
校验数据
python
import json
from urllib.request import urlopen
from jsonschema import validate # pip install jsonschema
# 固定到一个包含 schema/ 的 release tag;在第一个这样的版本发布之前,使用 main
TAG = "main"
BASE = f"https://raw.githubusercontent.com/pieterjanscheir/belgica/{TAG}"
courts = json.load(urlopen(f"{BASE}/data/courts.json"))
schema = json.load(urlopen(f"{BASE}/schema/courts.schema.json"))
validate(courts, schema)ts
import { Ajv } from 'ajv'
import addFormats from 'ajv-formats'
import courts from 'belgica/data/courts.json' with { type: 'json' }
import schema from 'belgica/schema/courts.schema.json' with { type: 'json' }
const ajv = new Ajv()
addFormats(ajv)
ajv.validate(schema, courts) // true当你保留了一份数据副本(例如加了额外记录的 fork,或缓存的下载文件),并想确认它仍然符合包所期望的结构时, 通常就会用到这一步。
为其他语言生成类型
由于这些 schema 遵循标准,你可以直接生成数据模型,而不必手写:Python(Pydantic)可用 datamodel-code-generator,C#、Go、Java、Kotlin、Swift 等 可用 quicktype。
bash
datamodel-codegen --input courts.schema.json --input-file-type jsonschema --output courts.pydatapackage.json
仓库根目录有一个 datapackage.json,它是 Frictionless Data Package 描述文件,即开放数据集的标准元数据文件。它列出每个数据文件的 标题、描述、schema、官方来源和许可,另外还有两个我们自定义的字段:
lastReviewed:最近一次根据来源核对该数据集的日期;reviewEveryMonths:需要多久重新核对一次。数据集逾期未核对时, 时效检查会自动开一个 issue。