Skip to content

Create a JSON Schema without the pain of writing it 🍦

License

Notifications You must be signed in to change notification settings

bjrmatos/json-schema-sugar

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

json-schema-sugar

NPM VersionLicenseBuild Status

Create a JSON Schema without the pain of writing it

This module let you write JSON Schemas v4 in a "sugar" way (using a chainable API). The API and style is stolen heavily inspired by Joi and Yup.

Usage

Define and create schema objects. Schema objects are immutable, so each call of a method returns a new schema object.

var sugar = require('json-schema-sugar');

var schema = sugar.object().keys({
  name: sugar.string().required(),
  age: sugar.number().integer().required(),
  email: sugar.string(),
  website: sugar.string()
});

var jsonSchema = schema.generate({
  name: 'jimmy',
  age: 24
});

console.log(jsonSchema);

Output:

{
  type: 'object',
  properties: {
    name: {
      type: 'string'
    },
    age: {
      type: 'integer'
    },
    email: {
      type: 'string'
    },
    website: {
      type: 'string'
    }
  },
  required: ['name', 'age']
}

API

sugar

The module export.

var sugar = require('json-schema-sugar');

sugar.mixed // also aliased as sugar.any
sugar.nullable
sugar.string
sugar.number
sugar.boolean
sugar.object
sugar.array

mixed

Creates a schema that matches a general type. All types inherit from this base type

var schema = sugar.mixed();
schema.generate();
// => {}

mixed.clone(): Schema

Creates a deep copy of the schema. Clone is used internally to return a new schema with every schema state change (making schema instances inmutable).

mixed.title(title: string): Schema

Adds a title in the schema.

mixed.description(description: string): Schema

Adds a description in the schema.

mixed.default(default: any): Schema

Adds a default value in the schema.

mixed.meta(field: string | object, value: ?any): Schema Alias: extra

Adds custom fields to the schema, multiple calls to .meta will accumulate data with previous calls.

With field:

var schema = sugar.object().keys({
  name: sugar.string().required().meta('example', 'Bob').meta('isMain', true),
});

schema.generate();

Output:

{
  type: 'object',
  properties: {
    name: {
      type: 'string',
      example: 'Bob',
      isMain: true
    }
  }
}

With an Object:

var schema = sugar.object().keys({
  name: sugar.string().required().meta({ example: 'Bob', isMain: true }),
});

schema.generate();

Output:

{
  type: 'object',
  properties: {
    name: {
      type: 'string',
      example: 'Bob',
      isMain: true
    }
  }
}

mixed.enum(values: Array<any>): Schema

Restricts a value in the schema to a fixed set of values.

mixed.required(): Schema

When used inside an object schema specifies that a property is required.

var schema = sugar.object().keys({
  name: sugar().string().required(),
  email: sugar().string().required(),
  address: sugar.string()
});

schema.generate();

Output:

{
  type: 'object',
  properties: {
    name: {
      type: 'string'
    },
    email: {
      type: 'string'
    },
    address: {
      type: 'string'
    }
  },
  required: ['name', 'email']
}

mixed.requiredWhen(dependantProp: string | Array<string>): Schema

When used inside an object schema specifies that a property must be present (required) when another property/properties are present, making a property dependency. dependantProp can be an array of strings, or multiple strings can be passed as individual arguments.

var schema = sugar.object().keys({
  name: sugar.string().required(),
  creditCard: sugar.number(),
  billingAddress: sugar.string().requiredWhen('creditCard', 'name'),
  billingDistrict: sugar.string().requiredWhen('creditCard')
});

schema.generate();

Output:

{
  type: 'object',
  properties: {
    name: {
      type: 'string'
    },
    creditCard: {
      type: 'number'
    },
    billingAddress: {
      type: 'string'
    },
    billingDistrict: {
      type: 'string'
    }
  },
  required: ['name'],
  dependencies: {
    creditCard: ['billingAddress', 'billingDistrict'],
    name: ['billingAddress']
  }
}

mixed.when(dependantProp: string | Array<string>): Schema

When used inside an object schema specifies that when a property is present the schema should be different, making a schema dependency. dependantProp can be an array of strings, or multiple strings can be passed as individual arguments.

var schema = sugar.object().keys({
  name: sugar.string(),
  creditCard: sugar.number(),
  billingAddress: sugar.mixed().when('creditCard', sugar.string().required())
});

schema.generate();

Output:

{
  type: 'object',
  properties: {
    name: {
      type: 'string'
    },
    creditCard: {
      type: 'number'
    }
  },
  dependencies: {
    creditCard: {
      properties: {
        billingAddress: {
          type: 'string'
        }
      },
      required: ['billingAddress']
    }
  }
}

mixed.definitions(definitions: object): Schema

Adds definitions to the schema, definitions are standardized placeholder in which you can define inline subschemas to be used in a schema.

var schema = sugar.object().keys({
  billingAddress: sugar.any().ref('#/definitions/address')
}).definitions({
  address: sugar.object().keys({
    streetAddress: sugar.string().required(),
    city: sugar.string().required(),
    state: sugar.string().required()
  })
});

schema.generate();

Output:

{
  type: 'object',
  properties: {
    billingAddress: {
      $ref: '#/definitions/address'
    }
  },
  definitions: {
    address: {
      type: 'object',
      properties: {
        streetAddress: {
          type: 'string'
        },
        city: {
          type: 'string'
        },
        state: {
          type: 'string'
        }
      },
      required: ['streetAddress', 'city', 'state']
    }
  }
}

mixed.allOf(schemas: Array<Schema>): Schema

Adds a restriction that the given data must be valid against all of the given subschemas.

var schema = sugar.mixed().allOf([
  sugar.string(),
  sugar.string().minLength(2),
  sugar.string().maxLength(5)
]);

Output:

{
  allOf: [{
    type: 'string'
  }, {
    minLength: 2
  }, {
    maxLength: 5
  }]
}

mixed.anyOf(schemas: Array<Schema>): Schema

Adds a restriction that the given data must be valid against any (one or more) of the given subschemas.

var schema = sugar.mixed().anyOf([
  sugar.string().maxLength(5),
  sugar.number().minimum(0)
]);

Output:

{
  anyOf: [{
    type: 'string',
    maxLength: 5
  }, {
    type: 'number',
    minimum: 0
  }]
}

mixed.oneOf(schemas: Array<Schema>): Schema

Adds a restriction that the given data must be valid against exactly one of the given subschemas.

var schema = sugar.mixed().oneOf([
  sugar.number().multipleOf(3),
  sugar.number().multipleOf(5)
]);

Output:

{
  oneOf: [{
    type: 'number',
    multipleOf: 3
  }, {
    type: 'number',
    multipleOf: 5
  }]
}

mixed.not(schema: Schema): Schema

Declares that a instance validates if it doesn’t validate against the given subschema.

var schema = sugar.mixed().not(sugar.string());

Output:

{
  not: {
    type: 'string'
  }
}

mixed.noType(): Schema

Declares that a schema should not include the type property in the output.

var schema = sugar.number().multipleOf(5).noType();

Output:

{
  multipleOf: 5
}

mixed.canBe(type: Schema | Array<Schema>): Schema

Specify multiple types for a schema. type can be an array of schemas, or multiple schemas can be passed as individual arguments. This method is only available to mixed schemas (schemas created directly with sugar.mixed())

var schema = sugar.mixed().canBe(sugar.string(), sugar.number());
schema.generate();
// => { type: ['string', 'number'] }

mixed.ref(refUri: string): Schema

Creates a reference to a schema located in refUri. This method is only available to mixed schemas (schemas created directly with sugar.mixed())

var schema = sugar.object().keys({
  billingAddress: sugar.any().ref('#/definitions/address'),
  shippingAddress: sugar.any().allOf([
    sugar.any().ref('#/definitions/address'),
    sugar.object().keys({
      type: sugar.any().enum(['residential', 'business']).required()
    })
  ])
}).definitions({
  address: sugar.object().keys({
    streetAddress: sugar.string().required(),
    city: sugar.string().required(),
    state: sugar.string().required()
  })
});

Output:

{
  type: 'object',
  properties: {
    billingAddress: {
      $ref: '#/definitions/address'
    },
    shippingAddress: {
      allOf: [{
        $ref: '#/definitions/address'
      }, {
        properties: {
          type: {
            enum: ['residential', 'business']
          }
        },
        required: ['type']
      }]
    }
  },
  definitions: {
    address: {
      type: 'object',
      properties: {
        streetAddress: {
          type: 'string'
        },
        city: {
          type: 'string'
        },
        state: {
          type: 'string'
        }
      },
      required: ['streetAddress', 'city', 'state']
    }
  }
}

mixed.generate(options: ?object): string

Generates a JSON Schema based on the constructed schema.

The options (optional) argument is an object hash and can contain the following properties:

options = {
  obj: boolean = false,
  removeType: boolean = false,
  space: ?number = undefined,
  $schema: ?string = undefined,
  id: ?string = undefined
};
  • obj: return the JSON Schema as object instead of string.
  • removeType: don't include the type property in the JSON Schema.
  • space: Specifies the space option for JSON.stringify, adding the ability to return the json string with white space.
  • $schema: Specifies a custom $schema entry in the JSON Schema.
  • id: Specifies an id entry in the JSON Schema.

nullable

Creates a schema that matches a null type. Supports all the same methods as mixed.

var schema = sugar.nullable();
schema.generate();
// => { type: 'null' }

boolean

Creates a schema that matches a boolean type. Supports all the same methods as mixed.

var schema = sugar.boolean();
schema.generate();
// => { type: 'boolean' }

number

Creates a schema that matches a number type. Supports all the same methods as mixed.

var schema = sugar.number();
schema.generate();
// => { type: 'number' }

number.integer(): Schema

Defines that the schema should be an integer.

var schema = sugar.number().integer();
schema.generate();

Output:

{
  type: 'integer'
}

number.multipleOf(value: number): Schema

Defines that the schema should be multiple of value.

var schema = sugar.number().multipleOf(3);
schema.generate();

Output:

{
  type: 'number',
  multipleOf: 3
}

number.minimum(value: number): Schema

Defines that the schema should be a minimum numeric value.

var schema = sugar.number().minimum(5);
schema.generate();

Output:

{
  type: 'number',
  minimum: 5
}

number.maximum(value: number): Schema

Defines that the schema should be a maximum numeric value.

var schema = sugar.number().maximum(10);
schema.generate();

Output:

{
  type: 'number',
  maximum: 10
}

number.exclusiveMinimum(value: boolean): Schema

When value is true, it indicates that the range excludes the minimum value, i.e., x > minx > min. When false (or not included), it indicates that the range includes the minimum value, i.e., x ≥ minx ≥ min.

var schema = sugar.number().minimum(5).exclusiveMinimum(true);
schema.generate();

Output:

{
  type: 'number',
  minimum: 5,
  exclusiveMinimum: true
}

number.exclusiveMaximum(value: boolean): Schema

When value is true, it indicates that the range excludes the maximum value, i.e., x < maxx <max. When false (or not included), it indicates that the range includes the maximum value, i.e., x ≤ maxx ≤ max.

var schema = sugar.number().maximum(10).exclusiveMaximum(true);
schema.generate();

Output:

{
  type: 'number',
  maximum: 10,
  exclusiveMaximum: true
}

string

Creates a schema that matches a string type. Supports all the same methods as mixed.

var schema = sugar.string();
schema.generate();
// => { type: 'string' }

string.minLength(value: number): Schema

Defines that a string should have a minimum length of value.

var schema = sugar.string().minLength(2);
schema.generate();

Output:

{
  type: 'string',
  minLength: 2
}

string.maxLength(value: number): Schema

Defines that a string should have a maximum length of value.

var schema = sugar.string().maxLength(8);
schema.generate();

Output:

{
  type: 'string',
  maxLength: 8
}

string.pattern(pattern: string | RegExp): Schema

Defines that a string should satisfies a pattern.

var schema = sugar.string().pattern(/abc/);
schema.generate();

Output:

{
  type: 'string',
  pattern: 'abc'
}

string.format(format: string): Schema

Defines a format for the string. format can be any standardized format like date-time, email, etc.

var schema = sugar.string().format('email');
schema.generate();

Output:

{
  type: 'string',
  format: 'email'
}

object

Creates a schema that matches a object type. Supports all the same methods as mixed.

var schema = sugar.object().keys({
  name: sugar.string()
});

schema.generate();
// => { type: 'object', properties: { name: { type: 'string' } } }

object.keys(properties: object): Schema

Defines properties for the object. Each key in the properties hash object must have a Schema as value.

var schema = sugar.object().keys({
  foo: sugar.boolean(),
  value: sugar.number(),
  address: sugar.string(),
  unknown: sugar.nullable()
});

schema.generate();

Output:

{
  type: 'object',
  properties: {
    foo: {
      type: 'boolean'
    },
    value: {
      type: 'number'
    },
    address: {
      type: 'string'
    },
    unknown: {
      type: 'null'
    }
  }
}

object.additionalProperties(value: boolean | Schema): Schema

Defines if an object can have additional properties or not. If value is a Schema then all additional properties must be valid against the given schema.

var schema = sugar.object().keys({
  foo: sugar.boolean(),
  value: sugar.number(),
  address: sugar.string(),
  unknown: sugar.nullable()
}).additionalProperties(sugar.string());

schema.generate();

Output:

{
  type: 'object',
  properties: {
    foo: {
      type: 'boolean'
    },
    value: {
      type: 'number'
    },
    address: {
      type: 'string'
    },
    unknown: {
      type: 'null'
    }
  },
  additionalProperties: {
    type: 'string'
  }
}

object.patternProperties(value: object): Schema

Defines that if there is any property in an object that match a given pattern, that property must be valid against a schema.

Each key in the value hash object must have a Schema as value.

var schema = sugar.object().keys({
  foo: sugar.boolean(),
  value: sugar.number(),
  address: sugar.string(),
  unknown: sugar.nullable()
}).patternProperties({
  '^S_': sugar.string(),
  '^I_': sugar.number().integer()
});

schema.generate();

Output:

{
  type: 'object',
  properties: {
    foo: {
      type: 'boolean'
    },
    value: {
      type: 'number'
    },
    address: {
      type: 'string'
    },
    unknown: {
      type: 'null'
    }
  },
  patternProperties: {
    '^S_': {
      type: 'string'
    },
    '^I_': {
      type: 'integer'
    }
  }
}

object.minProperties(value: number): Schema

Defines that an object should have a minimum number of properties.

var schema = sugar.object().keys({
  foo: sugar.boolean(),
  value: sugar.number(),
  address: sugar.string(),
  unknown: sugar.nullable()
}).minProperties(2);

schema.generate();

Output:

{
  type: 'object',
  properties: {
    foo: {
      type: 'boolean'
    },
    value: {
      type: 'number'
    },
    address: {
      type: 'string'
    },
    unknown: {
      type: 'null'
    }
  },
  minProperties: 2
}

object.maxProperties(value: number): Schema

Defines that an object should have a maximum number of properties.

var schema = sugar.object().keys({
  foo: sugar.boolean(),
  value: sugar.number(),
  address: sugar.string(),
  unknown: sugar.nullable()
}).maxProperties(3);

schema.generate();

Output:

{
  type: 'object',
  properties: {
    foo: {
      type: 'boolean'
    },
    value: {
      type: 'number'
    },
    address: {
      type: 'string'
    },
    unknown: {
      type: 'null'
    }
  },
  maxProperties: 3
}

array

Creates a schema that matches a array type. Supports all the same methods as mixed.

var schema = sugar.array().items(sugar.number());
schema.generate();
// => { type: 'array', items: { type: 'number' } }

array.items(items: object | Schema | Array<Schema>): Schema

When items is an object or Schema specifies that all items in an array must be valid against the given schema. When items is an array specifies that items in an array must be valid and appear in the same order of the given schemas (tuple validation).

var schema = sugar.array().items({
  name: sugar.string(),
  email: sugar.string()
});

schema.generate();

Output:

{
  type: 'array',
  items: {
    type: 'object',
    properties: {
      name: {
        type: 'string'
      },
      email: {
        type: 'string'
      }
    }
  }
}

Tuple example:

var schema = sugar.array().items([
  sugar.number(),
  sugar.string()
]);

schema.generate();

Output:

{
  type: 'array',
  items: [{
    type: 'number'
  }, {
    type: 'string'
  }]
}

array.additionalItems(value: boolean): Schema

Defines if an array can have additional items or not.

var schema = sugar.array().items([
  sugar.string(),
  sugar.number()
]).additionalItems(false);

schema.generate();

Output:

{
  type: 'array',
  items: [{
    type: 'string'
  }, {
    type: 'number'
  }],
  additionalItems: false
}

array.minItems(value: number): Schema

Defines that an array should have a minimum number of items.

var schema = sugar.array().items({
  value: sugar.number()
}).minItems(2);

schema.generate();

Output:

{
  type: 'array',
  items: {
    type: 'object',
    properties: {
      value: {
        type: 'number'
      }
    }
  },
  minItems: 2
}

array.maxItems(value: number): Schema

Defines that an array should have a maximum number of items.

var schema = sugar.array().items({
  value: sugar.number()
}).maxItems(2);

schema.generate();

Output:

{
  type: 'array',
  items: {
    type: 'object',
    properties: {
      value: {
        type: 'number'
      }
    }
  },
  maxItems: 2
}

array.uniqueItems(value: boolean): Schema

Defines that items in an array should be unique.

var schema = sugar.array().items({
  value: sugar.number()
}).uniqueItems(true);

schema.generate();

Output:

{
  type: 'array',
  items: {
    type: 'object',
    properties: {
      value: {
        type: 'number'
      }
    }
  },
  uniqueItems: true
}

About

Create a JSON Schema without the pain of writing it 🍦

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published