0.3.1 • Published 1 month ago

@cnz.com/ts-json v0.3.1

Weekly downloads
-
License
Apache-2.0
Repository
gitlab
Last release
1 month ago

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.

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.")
    }
}
0.3.1

1 month ago

0.3.0

2 months ago

0.2.1

8 months ago

0.2.3

6 months ago

0.2.2

7 months ago

0.2.0

1 year ago

0.1.15

1 year ago

0.1.14

1 year ago

0.1.13

2 years ago

0.1.11

2 years ago

0.1.12

2 years ago

0.1.10

2 years ago

0.1.8

2 years ago

0.1.9

2 years ago

0.1.7

2 years ago

0.1.6

2 years ago

0.1.4

3 years ago

0.1.5

2 years ago

0.1.3

3 years ago

0.1.2

3 years ago

0.1.1

3 years ago

0.1.0

3 years ago