npm package: @jsonhero/schema-generator
Description: Generate a draft-07 JSON schema definitions from an example JSON document
Author: Eric Allam
Latest version: 0.2.2

# Schema Generator

> Generate a draft-07 JSON schema definitions from an example JSON document

![Coverage lines](./badges/badge-lines.svg)

## Features

- Generate a draft-07 JSON schema definitions from an example JSON document
- Easy to use
- Supports string formats (with more to come)
- Can generate either a strict or liberal schema

## Usage

Install Schema Generator

```bash
$ npm install --save @jsonhero/schema-generator
```

`generateSchema` takes either a JSON object/array or JSON stringified and returns a valid draft-07 JSON Schema

```js
const { generateSchema } = require("@jsonhero/schema-generator");

const exampleJSON = {
  id: 1234,
  name: "Eric",
  image: {
    url: "https://foo.com/image.png",
  },
  email: "eallam@icloud.com",
  homepage: "http://github.com/ericallam",
  createdAt: "2021-12-17T12:55:58.141Z",
  tags: ["foo", "bar"],
  isAdmin: true,
};

const schema = generateSchema(exampleJSON);

// Now validate the provided JSON using the generated schema using ajv
const Ajv = require("ajv");
const ajv = new Ajv();
const addFormats = require("ajv-formats");
addFormats(ajv);

const validate = ajv.compile(schema);
const valid = validate(exampleJSON); // valid == true
```

The Schema generated in the above example

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://jsonhero.io/schemas/root.json",
  "type": "object",
  "properties": {
    "id": {
      "type": "number"
    },
    "name": {
      "type": "string"
    },
    "image": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "required": [],
      "additionalProperties": true
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "homepage": {
      "type": "string",
      "format": "uri"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "friends": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [],
        "additionalProperties": true
      }
    },
    "isAdmin": {
      "type": "boolean"
    }
  },
  "required": [],
  "additionalProperties": true
}
```

By default all `properties` are optional and `additionalProperties` are allowed. You can set the `strict` option to `true` if you'd like a more restrictive schema

```js
const { generateSchema } = require("@jsonhero/schema-generator");

const exampleJSON = {
  id: 1234,
  name: "Eric",
  image: {
    url: "https://foo.com/image.png",
  },
  email: "eallam@icloud.com",
  homepage: "http://github.com/ericallam",
  createdAt: "2021-12-17T12:55:58.141Z",
  tags: ["foo", "bar"],
  isAdmin: true,
};

const schema = generateSchema(exampleJSON, { strict: true });

// Now validate the provided JSON using the generated schema using ajv
const Ajv = require("ajv");
const ajv = new Ajv();
const addFormats = require("ajv-formats");
addFormats(ajv);

const validate = ajv.compile(schema);
const valid = validate(exampleJSON); // valid == true
```

The Schema generated in the above example

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://jsonhero.io/schemas/root.json",
  "type": "object",
  "properties": {
    "id": {
      "type": "number"
    },
    "name": {
      "type": "string"
    },
    "image": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string",
          "format": "image"
        }
      },
      "required": ["url"],
      "additionalProperties": false
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "homepage": {
      "type": "string",
      "format": "uri"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "friends": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"],
        "additionalProperties": false
      }
    },
    "isAdmin": {
      "type": "boolean"
    }
  },
  "required": [
    "id",
    "name",
    "image",
    "email",
    "homepage",
    "createdAt",
    "tags",
    "friends",
    "isAdmin"
  ],
  "additionalProperties": false
}
```

Generate Schema currently supports a few string formats

- Strings that are URLs will have the `uri` format
- Strings that are Date/Times will have the `date-time` format
- Strings that are emails will have the `email` format

If you are using `ajv` to use the generated schema, make sure to use the [ajv-formats](https://www.npmjs.com/package/ajv-formats) package

```js
const addFormats = require("ajv-formats");
addFormats(ajv);
```

You can also set the baseURI of the schema (i.e. the top level `$id` property)

```js
const { generateSchema } = require("@jsonhero/schema-generator");

const exampleJSON = {
  foo: "bar",
};

const schema = generateSchema(exampleJSON, {
  baseURI: "https://example.com/schemas/root.json",
});
```

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://example.com/schemas/root.json",
  "type": "object",
  "properties": {
    "foo": {
      "type": "string"
    }
  },
  "required": [],
  "additionalProperties": true
}
```

# Roadmap

- [ ] Support more draft versions of JSON Schema
- [ ] Support JSON Type Definitions
- [ ] Support enums and constants
- [ ] Support more string formats (regex, ipv4, ipv6, hostname, JSONPointer, time, date, uuid)
- [ ] Add examples