// product.schema.json { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "http://example.com/product.schema.json", "title": "Product", "description": "A product in the catalog", "type": "object", "properties": { "productId": { "description": "The unique identifier for a product", "type": "integer" } }, "required": [ "productId" ] } // input.json { "productId": 1 }
(import (rnrs) (text json) (text json validator) (text json schema)) (define product-validator (json-schema->json-validator (call-with-input-file "product.schema.json" json-read))) (validate-json product-validator (call-with-input-file "input.json" json-read)) ;; -> #tもう少し凝った例を見てみる。本当ならhttps://json-schema.org/learn/にあるのを直接使いたかったが、どうもあまりメンテされてないらしく不整合があって使えなかった。なので、ちょっと長いがSchemaをだらだら書く。
// address.schema.json { "$id": "http://example.com/address.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "An address similar to http://microformats.org/wiki/h-card", "type": "object", "properties": { "post-office-box": { "type": "string" }, "extended-address": { "type": "string" }, "street-address": { "type": "string" }, "locality": { "type": "string" }, "region": { "type": "string" }, "postal-code": { "type": "string" }, "country-name": { "type": "string" } }, "required": [ "locality", "region", "country-name" ], "dependencies": { "post-office-box": [ "street-address" ], "extended-address": [ "street-address" ] } } // geographical-location.schema.json { "$id": "http://example.com/geographical-location.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "title": "Longitude and Latitude Values", "description": "A geographical coordinate.", "required": [ "latitude", "longitude" ], "type": "object", "properties": { "latitude": { "type": "number", "minimum": -90, "maximum": 90 }, "longitude": { "type": "number", "minimum": -180, "maximum": 180 } } } // card.schema.json { "$id": "http://example.com/card.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "A representation of a person, company, organization, or place"\ , "type": "object", "required": [ "familyName", "givenName" ], "properties": { "fn": { "description": "Formatted Name", "type": "string" }, "familyName": { "type": "string" }, "givenName": { "type": "string" }, "additionalName": { "type": "array", "items": { "type": "string" } }, "honorificPrefix": { "type": "array", "items": { "type": "string" } }, "honorificSuffix": { "type": "array", "items": { "type": "string" } }, "nickname": { "type": "string" }, "url": { "type": "string" }, "email": { "type": "object", "properties": { "type": { "type": "string" }, "value": { "type": "string" } } }, "tel": { "type": "object", "properties": { "type": { "type": "string" }, "value": { "type": "string" } } }, "adr": { "$ref": "http://example.com/address.schema.json" }, "geo": { "$ref": "http://example.com/geographical-location.schema.json" }, "tz": { "type": "string" }, "photo": { "type": "string" }, "logo": { "type": "string" }, "sound": { "type": "string" }, "bday": { "type": "string" }, "title": { "type": "string" }, "role": { "type": "string" }, "org": { "type": "object", "properties": { "organizationName": { "type": "string" }, "organizationUnit": { "type": "string" } } } } } // card.json { "familyName": "Kato", "givenName": "Takashi", "adr": { "locality": "locality", "region": "region", "country-name": "The Netherlands" }, "geo": { "latitude": 10, "longitude": 90 } }バリデーションコードは以下
(import (rnrs) (text json) (text json schema) (text json validator) (srfi :26 cut)) (let* ((validators (map json-schema->json-validator (map (cut call-with-input-file <> json-read) '("address.schema.json" "geographical-location.schema.json")))) (validator (apply json-schema->json-validator (call-with-input-file "card.schema.json" json-read) validators))) (validate-json validator (call-with-input-file "card.json" json-read))) ;; -> #t
一応公式Githubにあるテストは全部通る(ドラフト7、オプショナル除く)。
余談だが、最近書いたYAMLパーサと組み合わせることもできる。以下はカードYAML
--- familyName: Kato givenName: Takashi adr: locality: locality region: region country-name: The Netherlands geo: latitude: 10 longitude: 90っで、コード
(import (rnrs) (text json) (text json schema) (text json validator) (text yaml) (srfi :26 cut)) (let* ((validators (map json-schema->json-validator (map (cut call-with-input-file <> json-read) '("address.schema.json" "geographical-location.schema.json")))) (validator (apply json-schema->json-validator (call-with-input-file "card.schema.json" json-read) validators))) (map (cut validate-json validator <>) (call-with-input-file "card.yaml" yaml-read))) ;; -> (#t)YAMLはドキュメントのリストを返すので
map
辺りでリストを回す必要がある。便利に使えそうな雰囲気がある。