Skip to content

Repository files navigation

npmnpm bundle sizeTypeScriptLicense

CodableJSON is a declarative JSON serialization library that aims to enable a whole new paradigm of data serialization in TypeScript/JavaScript.

Using modern decorators (@codableClass and @codable), you can mark your data model classes as serializable instead of writing custom (to/from) JSON functions.

Besides that, it's 3x faster SuperJSON alternative.

Key Features

  • Declarative and extensible: Mark props and classes as serializable instead of writing custom (to/from) JSON functions.
  • SuperJSON drop-in replacement: ~3x faster than SuperJSON (see benchmark)
  • Type-safe: Full TypeScript support with autocompletion and type inference
  • Zero dependencies: Fully standalone, no external dependencies. Less than 10KB gziped.
  • Well tested: Every feature is covered by tests. It passes most of SuperJSON tests moved into CodableJSON (including plenty of edge cases)
  • Framework agnostic: Works with any JavaScript/TypeScript project
  • Secure: Built-in protection against prototype pollution
  • Temporal API support: Automatically supports all modern "date" Temporal API types when Temporal is available globally: Instant, Duration, PlainDate, PlainDateTime, PlainMonthDay, PlainTime, PlainYearMonth, and ZonedDateTime.

Installation

npm install codablejson
yarn add codablejson
pnpm add codablejson

Quick start

1. JSON Serialization

Besides declarative framework (described below), it is also an ultra-fast SuperJSON alternative that can encode/decode almost any JavaScript input.

import{encode,decode}from"codablejson";constdata={date: newDate("2025-01-01"),map: newMap([["key","value"]]),};constencoded=encode(data);// {// date: { $$Date: "2025-01-01T00:00:00.000Z" },// map: { $$Map: [["key", "value"]] },// }constdecoded=decode(encoded);// fully equals to the original data

2. Declarative Class Serialization

Instead of writing custom (to/from) JSON functions, you can mark your classes and properties as serializable with modern decorators.

Let's define some classes and mark them as serializable:

import{codableClass,codable,Coder}from"codablejson";
@codableClass("Player")classPlayer{
@codable()name: string;
@codable()score: number;// Note: constructor is not needed for CodableJSON to work, it is here for convenience of creating instances.constructor(data: Pick<Player,"name"|"score">){this.name=data.name;this.score=data.score;}}
@codableClass("GameState")classGameState{
@codable()players: Set<Player>=newSet();
@codable()createdAt=newDate();
@codable()activePlayer: Player|null=null;addPlayer(player: Player){this.players.add(player);this.activePlayer=player;}}// Use your classes naturallyconstgameState=newGameState();gameState.addPlayer(newPlayer({name: "Alice",score: 100}));

Now, let's create a custom coder instance that is aware of our classes:

constcoder=newCoder([GameState,Player]);

Now, we can serialize our game state:

constencoded=coder.encode(gameState);

Will be serialized as:

{
"$$GameState": [
{
"players": {
"$$Set": [
{
"$$Player": [
{
"$$id": 0,
"name": "Foo",
"score": 100
}
]
}
]
},
"createdAt": { "$$Date": "2025-11-27T23:00:00.000Z" },
"activePlayer": { "$$ref": 0 }
}
]
}

We can decode it back to our original data. All types, references, and circular dependencies are preserved!

constdecoded=coder.decode<GameState>(encoded);

Note

Note: for classes to be automatically serialized, some conventions need to be followed. Read more about it here.

Built-in Types

Out of the box, CodableJSON handles most of the built-in JavaScript types:

Date, BigInt, Set, Map, RegExp, Symbol, URL, URLSearchParams, Error, undefined, typed arrays, special numbers like NaN, Infinity, -Infinity, -0 (treated as null by regular JSON).

Read more about supported types →

Temporal API Support

CodableJSON automatically supports all modern Temporal API types when Temporal is available globally: Instant, Duration, PlainDate, PlainDateTime, PlainMonthDay, PlainTime, PlainYearMonth, and ZonedDateTime. If your environment doesn't natively support Temporal, import a polyfill before using CodableJSON:

// import "temporal-polyfill/global"; // you need this if your environment doesn't natively support Temporalimport{encode,decode}from"codablejson";constinstant=Temporal.Instant.from("1970-01-01T00:00:00Z");constencoded=encode(instant);// { $$Instant: "1970-01-01T00:00:00Z" }constdecoded=decode(encoded);// decoded instanceof Temporal.Instant === true// Calculate duration between datesconststart=Temporal.PlainDate.from("2024-01-01");constend=Temporal.PlainDate.from("2025-12-25");constduration=start.until(end);constencodedDuration=encode(duration);// { $$Duration: "P1Y11M24D" }

Read more about Temporal support →

Performance

CodableJSON is heavily optimized for performance:

  • Encoding: ~3-3.5x faster than SuperJSON across all data sizes and types
  • Decoding: Comparable to or faster than SuperJSON depending on the data type

View detailed benchmarks →

API Overview

Core Functions

import{encode,decode,stringify,parse,clone}from"codablejson";// Basic encoding/decodingconstencoded=encode(data);constdecoded=decode(encoded);// With JSON stringificationconstjsonString=stringify(data);constrestored=parse(jsonString);// Deep clone maintaining all types and references equalityconstfoo={foo: "foo"};constoriginal=[foo,foo];constcloned=clone(original);// cloned === original; // false// cloned[0] === original[0]; // false -> nested clone// cloned[0] === cloned[1]; // true -> reference equality is preserved

Declarative Class Serialization

import{codableClass,codable,Coder}from"codablejson";
@codableClass("MyClass")classMyClass{
@codable()property: string;}constcoder=newCoder([MyClass]);constencoded=coder.encode(instance);constdecoded=coder.decode<MyClass>(encoded);

Custom Types

Read more about custom types →

You can also use lower-level API to create custom types and encode/decode them manually.

import{codableType,Coder}from"codablejson";const$$custom=codableType("CustomType",// name of the type(value)=>valueinstanceofCustomType,// how to detect some value should be encoded using this type(instance)=>instance.data,// how to encode the value (might return rich data like `Map` or `Set`, or even other custom types)(data)=>newCustomType(data),// how to recreate the value from the encoded data);constcoder=newCoder([$$custom]);// orconstcoder=newCoder();coder.register($$custom);

License

MIT

About

Declarative JSON serialization library that aims to enable a whole new paradigm of data serialization in TypeScript/JavaScript. Also, 3x faster SuperJSON alternative.

Topics

Resources

Stars

191 stars

Watchers

2 watching

Forks

Contributors

Languages