json-typescript-decoder v0.1.3
Typescript JSON decoder
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.
Usage
Generate typescript code from JSON schema
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);
Include Ajv in your package.json
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
Enable Javascript in your tsconfig.json
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
.
Example
Example JSON Schema
{
"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
}
}
}
Decode from JSON
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" });
Generated Typescript:
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");
}
Useful Ajv options
See https://github.com/epoberezkin/ajv#options for a complete list of Ajv options.
removeAdditional
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.
Example
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.