Generates Typescript typings and decoders from a JSON schema that will validate and convert json to the correct Typescript typings. The generated decoders allow you to consume JSON in a type-safe way.
Under the hood this package combines the power of json-schema-to-typescript and Ajv and Ajv-Pack with generated decoders.
The JSON validation methods are pre-generated for super-fast validation at runtime.
const generateFromFile = require('json-typescript-decoder').generateFromFile;
generateFromFile(
'schema.json', // The input schema
'sample', // The output folder
options: { // Optional options
// Custom decoder name, by default <OutputFolder>Decoder
decoderName: 'MySampleDecoder',
// Prettier configuration for generated Typescript
// See https://prettier.io/docs/en/options.html
style: { singleQuote: true, trailingComma: 'all' },
// Ajv options for generated code
// See https://github.com/epoberezkin/ajv#options
ajvOptions: { removeAdditional: true },
},
).catch(console.error);
Ajv should still be a run-time dependency, but generated modules will only depend on some parts of it, the whole Ajv will not be included in the bundle if you require these modules from your code.
npm install ajv
Because the generated validator functions from Ajv-Pack are Javascript, you need to enable Javascript in your tsconfig.json
.
Add "allowJs": true
to the compilerOptions
.
{
"definitions": {
"address": {
"type": "object",
"properties": {
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" }
},
"required": ["street_address", "city", "state"],
"additionalProperties": false
},
"person": {
"type": "object",
"properties": {
"firstName": { "type": "string" },
"lastName": { "type": "string" },
"address": { "$ref": "#/definitions/address" }
},
"required": ["firstName", "lastName"],
"additionalProperties": false
}
}
}
import { SampleDecoder } from './sample';
// 👍 Person type is returned and we know for sure that the JSON is valid
const validPerson = SampleDecoder.Person({ firstName: "John", lastName: "Doe" });
// 💥 Throws an error: should have required property 'lastName'
const invalidPerson = SampleDecoder.Person({ firstName: "John" });
This is what the generated code looks like (more or less).
// Import Javascript validator functions generated by Ajv-Pack
import * as Address$validate from "./Address.validate.js";
import * as Person$validate from "./Person.validate.js";
export interface Address {
street_address: string;
city: string;
state: string;
}
export interface Person {
firstName: string;
lastName: string;
address?: Address;
}
// ~~~ some generated utility functions here ~~~
export class SampleDecoder {
static Address = decode<Address>(Address$validate, "Address");
static Person = decode<Person>(Person$validate, "Person");
}
See https://github.com/epoberezkin/ajv#options for a complete list of Ajv options.
By default, if you specify "additionalProperties": false
in your JSON schema, schema validation fails if there are additional properties in the JSON. Sometimes you don't want this behaviour because, for example, a REST api may add properties to the JSON output and you don't want old version of you code to crash.
If you specify removeAdditional: true
in the ajvOptions
then all additional properties will be removed from the input JSON and schema validation will pass.
Too clarify, an example based on the above schema.
// Without removeAdditional
// Will fail with an error because JSON has a additional property 'age'
console.info(SampleDecoder.Person({ firstName: "John", lastName: "Doe", age: 30 }));
// With removeAdditional = true
// Succeeds and age property is stripped from the input JSON
// This will print { firstName: "John", lastName: "Doe" }
console.info(SampleDecoder.Person({ firstName: "John", lastName: "Doe", age: 30 }));
You can also pass "failing"
, "all"
and false
as a value for removeAdditional
. Please read the Ajv documentation for more information.