toonkit
Type-SafeCompactHuman-ReadableMIT

toonkit

A parser & serializer for TOON โ€” Typed Object Oriented Notation. Transform JSON to compact TOON format and back with built-in type awareness.

$ npm install toonkit
๐Ÿ“ฆ

What is toonkit?

Why TOON? Why this library?

toonkit provides a core parser/serializer and framework adapters for easy integration with HTTP clients and servers.

  • toonToJson(input: string) โ€” Parses TOON text into JavaScript objects
  • jsonToToon(obj: any) โ€” Serializes JavaScript objects to TOON format
  • Adapter exports โ€” `toonkit/express`, `toonkit/fastify`, `toonkit/hono`, `toonkit/next/server`, and a `toonkit/fetch` client for convenience.

Why TOON?

JSON is powerful but verbose. TOON solves this by separating the schema definition from the data rows โ€” like a typed table format. Result: smaller payloads, faster parsing, and type safety built in.

๐Ÿ“‰
40-60% smaller
No repeated key names
๐Ÿ”ค
Human-readable
Plain text, easy to edit
๐Ÿท๏ธ
Type-safe
Schema declares all types
โšก
Fast parsing
Minimal overhead structure
๐Ÿ“ฅ

Installation

npm
npm install toonkit
yarn
yarn add toonkit
pnpm
pnpm add toonkit
๐Ÿ”—

Import & Functions

ES Module Import
import { toonToJson, jsonToToon, toonFetch } from "toonkit";
import { toon } from "toonkit/express";
// or: import { toon } from "toonkit/fastify"

Function Signatures

toonToJson(input: string)Parses TOON text and returns a JavaScript object with all types resolved.
jsonToToon(obj: any)Converts a JavaScript object/array into TOON format string.
๐Ÿ”„

toonToJson()

Parse TOON strings into JavaScript objects

This function reads TOON-formatted text and automatically converts it to a properly-typed JavaScript object. Type codes in the schema determine how each value is parsed.

Usage
const toonString = `
device_id[1]{0:s}:
DEVICE_PRO_01

battery[1]{0:n}:
87

is_active[1]{0:b}:
true
`;

const json = toonToJson(toonString);
// json = { device_id: "DEVICE_PRO_01", battery: 87, is_active: true }

Type Codes Reference

CodeMeaningExampleOutput
sstringManoj"Manoj"
nnumber36.736.7
bbooleantruetrue
nlnullnullnull
jJSON object{"a":1}{ a: 1 }
aarray[1,2,3][1,2,3]
tdtext/date03042026120000"03042026120000"
Note: Type code j and a must contain valid JSON. Use td for raw text that shouldn't be parsed.

Complete Example

TOON Input
device_id[1]{0:s}:
DEVICE_PRO_01

battery[1]{0:n}:
87

temperature[1]{0:n}:
36.7

is_active[1]{0:b}:
true

last_error[1]{0:nl}:
null

location[1]{0:j}:
{"lat":12.9716,"lng":77.5946}

tags[1]{0:a}:
["iot","health","tracker"]

created_at[1]{0:td}:
03042026120000
JavaScript Output
{
  device_id: "DEVICE_PRO_01",
  battery: 87,
  temperature: 36.7,
  is_active: true,
  last_error: null,
  location: { lat: 12.9716, lng: 77.5946 },
  tags: ["iot", "health", "tracker"],
  created_at: "03042026120000"
}
๐Ÿ”„

jsonToToon()

Convert JavaScript objects to TOON format

This function inspects your JavaScript object and automatically detects the type of each value (null, string, number, boolean, array, object). It then generates the appropriate TOON-formatted string.

Type Detection Rules

  • null โ†’ nl
  • string โ†’ s
  • number โ†’ n
  • boolean โ†’ b
  • Array โ†’ a
  • Object โ†’ j (JSON)

Example

JavaScript Input
const obj = {
  device_id: "DEVICE_PRO_01",
  battery: 87,
  temperature: 36.7,
  is_active: true,
  last_error: null,
  location: { lat: 12.9716, lng: 77.5946 },
  tags: ["iot", "health", "tracker"]
};

const toon = jsonToToon(obj);
TOON Output
device_id[1]{0:s}:
DEVICE_PRO_01

battery[1]{0:n}:
87

temperature[1]{0:n}:
36.7

is_active[1]{0:b}:
true

last_error[1]{0:nl}:
null

location[1]{0:j}:
{"lat":12.9716,"lng":77.5946}

tags[1]{0:a}:
["iot","health","tracker"]
๐Ÿงฌ

Type Codes Reference

Complete guide to all supported data types

TOON uses single or two-letter codes to declare the type of each field. This allows toonToJson to parse values correctly and jsonToToon to detect types automatically.

sStringManojPlain text, no special escaping needed
nNumber87 or 36.7Integers and floats
bBooleantrue or falseLowercase only, case-sensitive
nlNullnullRepresents null/undefined values
jJSON Object{"a":1}Valid JSON object, auto-parsed
aArray[1,"a",true]Valid JSON array, auto-parsed
tdText/Date03042026120000Raw text, no parsing (good for date strings)
๐Ÿ–ฅ

Express.js Integration

Using toonkit in Node.js / Express APIs

toonkit works seamlessly with Express. Use express.text() middleware to accept TOON payloads and respond with TOON strings.

โš ๏ธ Required: Always call app.use(express.text()) before your routes. Without this, req.body will be empty.
๐Ÿงญ

Core parser & Frontend usage

How the main parser works and using TOON in browsers

The core of `toonkit` is the parser/serializer pair:

  • toonToJson(input: string) โ€” parse TOON text into typed JavaScript objects.
  • jsonToToon(obj: any) โ€” serialize JS objects into TOON text.

Using the parser in the browser

Two common front-end patterns: fetch the raw TOON response and parse locally, or use `toonFetch` which returns parsed data.

Manual fetch + parse
import { toonToJson } from "toonkit";

const res = await fetch("/api/devices");
const text = await res.text();
const data = toonToJson(text);
Using toonFetch (direct)
import { toonFetch } from "toonkit";

const result = await toonFetch("/api/devices");
const data = result.data; // already parsed
๐ŸŒ

Fetch client

`toonFetch`, `configureToonFetch`, and `createToonAxios` examples

`toonkit` provides a lightweight fetch wrapper and axios helpers that automatically handle TOON serialization and parsing, plus convenience token handling.

Basic GET

Basic GET
import { toonFetch } from "toonkit";

const res = await toonFetch("https://localhost:3000/users");
console.log(res.data);

GET with headers

GET With Headers
const res = await toonFetch("https://localhost:3000/users", {
  headers: {
    Authorization: "Bearer token123",
    "x-api-key": "abc123"
  }
});

console.log(res.data);

Token shortcut

Pass `token` as a string or function โ€” it's added as `Authorization: Bearer ...`.

Token (string)
const res = await toonFetch("https://localhost:3000/users", {
  token: "mytoken"
});

// header => Authorization: Bearer mytoken
Token (function)
const res = await toonFetch("https://localhost:3000/profile", {
  token: () => localStorage.getItem("jwt")
});

POST โ€” TOON body (default)

By default, providing `data` will serialize to TOON and set `Content-Type: application/toon`.

POST TOON
await await toonFetch("https://localhost:3000/users", {
  method: "POST",
  data: { name: "Manoj", age: 22 }
});

POST โ€” send JSON instead

Override `Content-Type` to `application/json` to send JSON payloads.

POST JSON
await await toonFetch("https://localhost:3000/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  data: { name: "Manoj" }
});

Full example (headers + token + body)

Full Example
const res = await toonFetch("https://localhost:3000/create-user", {
  method: "POST",
  token: "jwt_token_here",
  headers: { "x-app": "toonkit" },
  data: { username: "manoj", email: "manoj@gmail.com" }
});

console.log(res.data);

Configure global base URL

configureToonFetch
import { configureToonFetch } from "toonkit";

configureToonFetch({ baseURL: "https://api.example.com", token: () => localStorage.getItem("token") });

// now: await toonFetch('/users') -> https://api.example.com/users

Create a separate axios client

createToonAxios
import { createToonAxios } from "toonkit";

const api = createToonAxios({ baseURL: "https://api.example.com", token: "abc123" });

const users = await api.get("/users");
console.log(users.data);

Response format

toonFetch returns an object{ data, response } wheredata is already parsed JS (TOON or JSON) and response is a Fetch-like `Response` wrapper.

Response Format
const { data, response } = await toonFetch("/users");
console.log(data);
console.log(response.status);

Example Express backend

A simple Express route that accepts TOON text and returns a TOON response.

Express Backend
app.post("/users", express.text(), (req, res) => {
  console.log(req.body); // TOON string

  res.setHeader("Content-Type", "application/toon");

  res.send('name[1]{0:s}:
Manoj
age[1]{0:n}:
22');
});

Real usage example (login)

Login Example
const login = async () => {
  const { data } = await toonFetch("/login", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    data: { email: "manoj@gmail.com", password: "123456" }
  });

  console.log(data);
};
๐Ÿš€

Fastify Integration

Register plugin for request/response handling

Fastify users can register the `toon` plugin to parse TOON bodies and send TOON responses.

Fastify Plugin
import Fastify from "fastify";
import { toon } from "toonkit/fastify";

const app = Fastify();
await app.register(toon);

app.post("/devices", async (req, reply) => {
  const data = req.toon();
  reply.toon({ ok: true, received: data });
});
๐Ÿงฉ

Express plugin

Register middleware for Express

Express users can mount the `toon` middleware from `toonkit/express` to get `req.toon()` and `res.toon()` helpers.

Express Plugin
import express from "express";
import { toon } from "toonkit/express";

const app = express();
// Mount middleware (returns [parser, responder] or a single middleware depending on build)
app.use(...toon());

app.post("/devices", (req, res) => {
  const data = req.toon();
  res.toon({ ok: true, received: data });
});
๐Ÿ”—

Hono Integration

Middleware for Hono apps

Use the `toon` middleware for Hono to parse and respond with TOON.

Hono Middleware
import { Hono } from "hono";
import { toon } from "toonkit/hono";

const app = new Hono();
app.use("*", toon());

app.post("/devices", (c) => c.json({ ok: true, received: c.req.toon() }));
โš™๏ธ

Next.js (Edge/Server)

Parsing TOON in route handlers

Next server adapters expose `parseToonRequest` and `ToonResponse` helpers for route handlers.

Next.js Route
import { parseToonRequest, ToonResponse } from "toonkit/next/server";

export async function POST(req) {
  const body = await parseToonRequest(req);
  return ToonResponse.toon({ ok: true, received: body });
}
๐Ÿงช

Testing with Postman

Manual API testing with TOON payloads

Since TOON is plain text, testing is straightforward in Postman or any HTTP client. Follow these steps:

1
Set Method
Select POST or GET as needed
2
Add Header
Content-Type: text/plain
3
Raw Body
In Body tab, select raw โ†’ Text. Paste your TOON string.
4
Send
Hit Send. Response will be TOON text.

Example TOON Body

Postman Body (raw text)
device_id[1]{0:s}:
DEVICE_PRO_01

battery[1]{0:n}:
87

is_active[1]{0:b}:
true
โšก

Performance & Size

Why TOON is more efficient than JSON

JSON repeats every key name in every object. TOON declares the schema once, then uses compact row values. For tabular data with many rows, this saves significant bytes and parsing time.

Size Comparison

Same Data โ€” JSON vs TOON
// JSON: ~145 bytes
{"devices":[{"device_id":"DEVICE_PRO_01","battery":87,"is_active":true},{"device_id":"DEVICE_PRO_02","battery":92,"is_active":false}]}

// TOON: ~90 bytes (38% reduction)
devices[2]{device_id:s,battery:n,is_active:b}:
DEVICE_PRO_01,87,true
DEVICE_PRO_02,92,false
JSON
  • โŒ Keys repeated per row
  • โŒ Nested braces & quotes
  • โŒ Heavier for tables
  • โŒ More to parse
TOON
  • โœ… Keys declared once
  • โœ… CSV-style rows
  • โœ… Compact payloads
  • โœ… Faster to parse
Ready to use toonkit?

Install from npm, import the functions, and start converting between JSON and TOON. Perfect for REST APIs, bots, IoT devices, and any system where payload size matters.