0.1.5 • Published 2 years ago
@jsonhero/schema-infer v0.1.5
JSON Schema Infer
Infers JSON Schemas from example JSON. Powers the schema inference of jsonhero.io
Features
- Written in typescript
- Inspired by jtd-infer
- Generates valid 2020-12 JSON schema documents from example data
- Supports most string formats through json-infer-types
- Date and times
- URIs
- Email Addresses
- Hostnames
- IP Addresses
- uuids
- Supports snapshotting and restoring inference sessions
- Handles nullable values and required/optional properties
Usage
Install schema-infer
:
npm install --save @jsonhero/schema-infer
To produce a JSON Schema document, pass in the example JSON to inferSchema
and call toJSONSchema
on the result:
import { inferSchema } from "@jsonhero/schema-infer";
inferSchema({
id: "abeb8b52-e960-44dc-9e09-57bb00d6b441",
name: "Eric",
emailAddress: "eric@jsonhero.io",
website: "https://github.com/ericallam",
joined: "2022-01-01",
}).toJSONSchema();
Infers the following JSON schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": { "type": "string", "format": "uuid" },
"name": { "type": "string" },
"emailAddress": { "type": "string", "format": "email" },
"website": { "type": "string", "format": "uri" },
"joined": { "type": "string", "format": "date" }
},
"required": ["id", "name", "emailAddress", "website", "joined"]
}
Inferring an array of objects, with some properties being optional:
inferSchema([
{ rank: 1, name: "Eric", winner: true },
{ rank: 2, name: "Matt" },
]).toJSONSchema();
Produces the following schema:
{
"items": {
"properties": {
"name": {
"type": "string"
},
"rank": {
"type": "integer"
},
"winner": {
"type": "boolean"
}
},
"required": ["rank", "name"],
"type": "object"
},
"type": "array"
}
You can produce better results by inferring from more than 1 example JSON, like so:
let inference = inferSchema({ name: "Eric" });
inference = inferSchema({ name: "James", age: 87 });
inference.toJSONSchema();
Produces:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" }
},
"required": ["name"]
}
If you need to save the inference session for later use you can use the toSnapshot
and restoreSnapshot
functions:
let inference = inferSchema({ name: "Eric" });
let snapshot = inference.toSnapshot();
await writeFile("./inference.json", JSON.stringify(snapshot));
// Later:
let snapshot = JSON.parse(await readFile("./inference.json"));
inferSchema({ email: "eric@jsonhero.io" }, restoreSnapshot(snapshot));
This library makes use of anyOf
to handle a value that can be multiple conflicting types:
inferSchema([1, "three"]).toJSONSchema();
Will produce
{
"type": "array",
"items": {
"anyOf": [{ "type": "integer" }, { "type": "string" }]
}
}
Examples
Airtable API
Roadmap
- Add support for hints for discriminators (tagged unions), value-only schemas, and enums
- Add support for JSON Typedefs
- Add "verbose" mode to include
$id
,examples
, etc.