A lightweight, extensible JSON encoder and decoder which supports custom types.
NOTICE: Jasone is still in early development and might not be stable yet.
- 🚀 Fast & Lightweight: Minimal footprint.
- 🔌 Extensible: Easily add custom types.
- 💻 TypeScript: Written in TypeScript for type safety and better DX.
# npm
npm install jasone
# pnpm
pnpm add jasone
# yarn
yarn add jasone
# bun
bun add jasone
import { Jasone } from "jasone";
const data = { myDate: new Date("2025-04-05T14:30:00.000+02:00") };
const encoded = JSON.stringify(Jasone.encode(data));
console.log(encoded); // {"myDate":{"$":1,"timestamp":1743856200000}}
import { decode } from "jasone";
const encoded = '{"myDate":{"$":1,"timestamp":1743856200000}}';
const decoded = Jasone.decode(JSON.parse(encoded));
console.log(decoded); // { myDate: new Date("2025-04-05T14:30:00.000+02:00") }
Adding custom types is really easy. You just need to create an transformer object and register it with Jasone.
import { Jasone } from "jasone";
class Car {
constructor(public brand: string, public model: string) {}
// ...
}
// use the `createType` helper
const myType = createType({
// the match function is used to determine if the transformer can encode the given value
matches: (value) => value instanceof Car,
// the type id is used to identify the type on the encoded object
// (this needs to be unique and a string, numbers are currently reserved for built-in types)
typeId: "Car"
// the encode function which receives the matched value and need to return an valid JSON object
encode: (car) => ({ brand: car.brand, model: car.model }),
// the decode function which receives the encoded JSON object and needs to return a original value
decode: ({brand, model}) => new Car(brand, model),
});
For classes, you can also use a bit more performant way of creating the transformer object:
const myType = createType({
// by using the `target` property, under the hood, Jasone will use the constructor to match
// the type. Which is more performant than using the `matches` property.
target: Car,
typeId: "Car",
encode: (car) => ({brand: car.brand, model: car.model}),
decode: ({brand, model}) => new Car(brand, model),
});
Now the only thing left is to register the type with Jasone:
Jasone.register(myType);
And that's it! If you want multiple instances of Jasone with different types, simply create a new instance like so:
const jasone = new Jasone({
types: [myType],
});
Or
const jasone = new Jasone();
jasone.register(myType);
Contributions are welcome! Please open an issue or submit a pull request.
This project is licensed under the MIT License.