TypeScript JSON validator
ts-json is a library for validating JSON in TypeScript. It has the following design features.
1. Concise definition of the JSON validation.
2. Uses TypeScript as the engine of validation.
3. No code generation.
The steps involved in using ts-json for a given TypeScript interface are:
1. Define a list of validation rules for the interface as a TypeScript function.
2. Wrap each JSON object to be validated in a JsonValidator object to provide the validation functionality.
3. Invoke the validation rules function with this JsonValidator object.
The validation rules function will return a fully type-checked object of the type of the interface. Beyond type validation, arbitrary constraints may optionally be provided for each attribute.
This library also facilitates populating interfaces from environment variables.
``bash`
yarn add @cnz.com/ts-json
or
`bash`
npm install @cnz.com/ts-json
A single interface with a single level of attributes.
`typescript
interface Person {
id : number
name : string
}
// The JSON validation rules for Person.
const jvrPerson:JsonValidationRules
return {
id : v.validate
name : v.validate("name", JT.string)
}
}
`
Below shows how the above interface would be validated.
`typescript
const jsonPerson = {
id : 6,
name : "Patrick McGoohan"
}
const jv = new JsonValidator(jsonPerson)
try {
const person:Person = jvrPerson(jv)
} catch (e:unknown) {
if (e instanceof JsonError) {
console.log(JSON validation error: ${e.message})`
} else {
console.log("JSON validation failed with unknown error.")
}
}
A single interface with multiple levels of attributes, a library constraint (isPositiveInteger), and a custom constraint.
`typescript
interface Person {
id : number
name : string
address : {
city : string
stateCode : StateCode
}
}
const isStateCode:Constraint = (x) => x in StateCode
const jvrPerson:JsonValidationRules
return {
id : v.validate
name : v.validate("name", JT.string),
address : v.validateObject("address", (v:JsonValidator) => {
return {
city : v.validate("city", JT.string),
stateCode : v.validate
}
})
}
}
`
An interface with a second embedded interface. jvrAddress would be defined with the Address interface.
`typescript
interface PersonWithAddress {
id : number
name : string
address : Address
}
const jvrPersonWithAddress:JsonValidationRules
return {
id : v.validate
name : v.validate("name", JT.string),
address : v.validateObject("address", jvrAddress)
}
}
`
An interface populated from environment variables.
`typescript
const getJsonApiConfigFromEnv:getEnvAsJson = () => {
return {
url : getEnv("API_URL"),
key : getEnv("API_KEY"),
retries : getEnv
isEnabled : getEnv
}
}
interface ApiConfig {
url : string,
key : string,
retries : number
isEnabled : boolean,
}
const jvrApiConfig:JsonValidationRules
return {
url : v.validate("url", JT.string, isUrl),
key : v.validate("key", JT.string),
retries : v.validate
isEnabled : v.validate
}
}
`
Below shows how the above interface would be retrieved from the environment and validated.
`typescriptEnvironment validation error: ${e.message}
try {
const jsonApiConfig = getJsonApiConfigFromEnv()
const jvApiConfig = new JsonValidator(jsonApiConfig)
const apiConfig:ApiConfig = jvrApiConfig(jvApiConfig)
} catch (e:unknown) {
if (e instanceof EnvError) {
console.error()JSON validation error: ${e.message}
} else if (e instanceof JsonError) {
console.error()``
} else {
console.error("JSON validation failed with unknown error.")
}
}