An extension of JSON5 with rich inline type information.
TxJSON allows you to define typed values and define deserialisers for said values at runtime.
Syntax:
{
x: date "2001-01-01", // it can handle custom deserializers!
y: 123n, // it can handle `BigInt` out of the box!
z: /^I\sCAN\sPARSE\sREGEX$/im, // ...and also regular expressions!
backquote: `Hello
World!`, // multi-line template strings are supported! (sans placeholders)
w: undefined, // ...and even `undefined`!
}
Perfect for configuration files and programmatic generation of tests!
Perhaps, the best example of a TxJSON document is a TxJSON schema:
schema {
/// Use `:document` to restrict the type of a document's root.
":document": arrayOf Place,
// a literal object signature
Place: object {
// `id` can be a string or a number
id: oneOf [string, number],
name: string,
cat: Category,
// `maybe` makes the following type optional (e.g can be `undefined` or `null`)
description: maybe string,
coords: maybe oneOf [arrayOf Point, Point],
region: arrayOf Point,
address: maybe string,
phone: maybe string,
// `tags` is a dynamic string array of any length.
tags: maybe arrayOf string,
// You can pass literal values to match against. This can be used to define enums with `oneOf`!
status: oneOf ["published", "private", "hidden"],
},
Category: oneOf [
"accomodation",
"shopping",
"parks_and_recreation",
"restaurant",
],
// Definition of a GeoJSON point.
Point: oneOf [
// A plain object.
object {
type: "Point", // A fixed string!
coordinates: arrayOf [number, number, maybe number], // A fixed array signature
bbox: maybe arrayOf [number, number, number, number], // `maybe` makes this field optional
},
// A class version of the same object.
class [number, number]
],
}
This project requires NodeJS (version 8 or later) and NPM. Node and NPM are really easy to install. To make sure you have them available on your machine, try running the following command.
$ npm -v && node -v
6.4.1
v8.16.0
During development, you must have a version of Java installed, this is required by antlr4ng
for use in generating the parser.
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
BEFORE YOU INSTALL: please read the prerequisites
To install and set up the library, run:
$ npm install txjson
Or if you prefer using Yarn:
$ yarn add txjson
function parse<T>(
input: string,
schema?: Partial<ISchema>,
fileName?: string
): T
Parses a TxJSON file and returns a JavaScript value.
input: string
: The input to be parsed.
schema?: Partial<ISchema>
Field | Default value | Description |
---|---|---|
deserializers |
{...} | A mapping of [name]: Deserializer pairs |
validators |
{...} | A mapping of [name]: Validator pairs |
classes |
{...} | A mapping of user classes, constructible using the constructor syntax: MyClass(x, y, z) |
prototypes |
{...} | A mapping of user classes, constructible using the prototype assignment syntax: MyClass... { field1: "value", ... } |
preprocessors |
{...} | A mapping of user preprocessors, these will run before any validation occurs. |
meta |
{...} | A dictionary to store user metadata. |
If no schema is supplied, this function will use the default schema.
fileName?: string
: An optional file name to include in error messages.
Example:
import {parse} from "txjson";
parse(`12`); // ok
parse(`int 12`); // ok
parse(`float 12.3`); // ok
parse(`int 12.3`); // error!
function parseSchema(
document: string,
baseSchema?: Schema,
schemaFileName?: string
): Schema
Parses a schema document.
definition: string
: The schema string.
baseSchema?: Schema
: the original schema to extend/apply these definitions to. (optional)
schemaFileName?: string
: An optional file name to include in error messages.
Example:
import {parse, parseSchema} from "txjson";
const schema = parseSchema(`
schema {
intOrBigInt: oneOf [int, bigint],
optionalInt: maybe int,
strOrNumber: oneOf [string, number],
date: strOrNumber,
MyClass: class [string, number],
MyProto: proto {
a: string,
b: number,
},
}
`, {
classes: {
MyClass: class MyClass {
constructor(public a: string, public b: number) {}
}
},
prototypes: {
MyProto: class MyProto {
public a: string;
public b: number;
}
},
deserializers: {
'Date': (acc: ValueAccessor) => new Date(acc.rawValue),
}
})
parse(`intOrBigInt 1`) // ok
parse(`intOrBigInt int 1`) // ok
parse(`intOrBigInt bigint "123"`) // ok
parse(`intOrBigInt 123n`) // ok
parse(`intOrBigInt 13.3`) // error!
parse(`optionalInt null`) // ok
parse(`optionalInt 0`) // ok
parse(`optionalInt "x"`) // error!
parse(`date 0`) // ok!
parse(`date "2001-01-01"`) // ok!
parse(`date 123n`) // error!
parse(`MyClass("a", 2)`) // ok!
parse(`MyClass("a")`) // error, missing argument!
parse(`MyClass(1, 2)`) // error, invalid argument!
parse(`MyClass... {a: "a", b: 2}`) // error, not a proto!
parse(`MyProto... {a: "a", b: 2}`) // ok!
parse(`MyProto... {a: "a", b: 2, c: 212}`) // error, extra field!
parse(`MyProto... {a: 1, b: "a"}`) // error, invalid field!
parse(`MyProto... {a: 1}`) // error, missing field!
parse(`MyProto("a", 2)`) // error, constructor call on proto is not supported!
function createSchema(
overrides?: Partial<ISchema>
): Schema
Creates a new schema with default types. (e.g int
, bigint
, UInt8Array
, ...)
overrides
: (optional) Pass another schema to override the defaults.
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Add your changes:
git add .
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request 😎
We use SemVer for versioning. For the versions available, see the tags on this repository.
- Abdullah Ali - Initial work - GitHub
See also the list of contributors who participated in this project.
MIT License © Abdullah Ali