@cnz.com/ts-json v0.3.1
TypeScript JSON Validator
ts-json is a library for validating JSON in TypeScript. It has the following design features.
- Concise definition of the JSON validation.
- Uses TypeScript as the engine of validation.
- No code generation.
The steps involved in using ts-json for a given TypeScript interface are:
- Define a list of validation rules for the interface as a TypeScript function.
- Wrap each JSON object to be validated in a JsonValidator object to provide the validation functionality.
- 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.
Installation
yarn add @cnz.com/ts-json
or
npm install @cnz.com/ts-json
Example 1
A single interface with a single level of attributes.
interface Person {
id : number
name : string
}
// The JSON validation rules for Person.
const jvrPerson:JsonValidationRules<Person> = (v) => {
return {
id : v.validate<number>("id", JT.number),
name : v.validate("name", JT.string)
}
}
Below shows how the above interface would be validated.
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.")
}
}
Example 2
A single interface with multiple levels of attributes, a library constraint (isPositiveInteger
), and a custom constraint.
interface Person {
id : number
name : string
address : {
city : string
stateCode : StateCode
}
}
const isStateCode:Constraint = (x) => x in StateCode
const jvrPerson:JsonValidationRules<Person> = (v) => {
return {
id : v.validate<number>("id", JT.number, isPositiveInteger),
name : v.validate("name", JT.string),
address : v.validateObject("address", (v:JsonValidator) => {
return {
city : v.validate("city", JT.string),
stateCode : v.validate<StateCode>("stateCode", JT.string, isStateCode)
}
})
}
}
Example 3
An interface with a second embedded interface. jvrAddress would be defined with the Address interface.
interface PersonWithAddress {
id : number
name : string
address : Address
}
const jvrPersonWithAddress:JsonValidationRules<PersonWithAddress> = (v) => {
return {
id : v.validate<number>("id", JT.number, isPositiveInteger),
name : v.validate("name", JT.string),
address : v.validateObject("address", jvrAddress)
}
}
Example 4
An interface populated from environment variables.
const getJsonApiConfigFromEnv:getEnvAsJson = () => {
return {
url : getEnv("API_URL"),
key : getEnv("API_KEY"),
retries : getEnv<number>("API_RETRIES", envCastNumber),
isEnabled : getEnv<boolean>("API_ENABLED", envCastBoolean)
}
}
interface ApiConfig {
url : string,
key : string,
retries : number
isEnabled : boolean,
}
const jvrApiConfig:JsonValidationRules<ApiConfig> = (v) => {
return {
url : v.validate("url", JT.string, isUrl),
key : v.validate("key", JT.string),
retries : v.validate<number>("retries", JT.number, isPositiveInteger),
isEnabled : v.validate<boolean>("isEnabled", JT.boolean)
}
}
Below shows how the above interface would be retrieved from the environment and validated.
try {
const jsonApiConfig = getJsonApiConfigFromEnv()
const jvApiConfig = new JsonValidator(jsonApiConfig)
const apiConfig:ApiConfig = jvrApiConfig(jvApiConfig)
} catch (e:unknown) {
if (e instanceof EnvError) {
console.error(`Environment validation error: ${e.message}`)
} else if (e instanceof JsonError) {
console.error(`JSON validation error: ${e.message}`)
} else {
console.error("JSON validation failed with unknown error.")
}
}
1 month ago
2 months ago
8 months ago
6 months ago
7 months ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago