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 objectsjsonToToon(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.
Installation
npm install toonkityarn add toonkitpnpm add toonkitImport & Functions
import { toonToJson, jsonToToon, toonFetch } from "toonkit"; import { toon } from "toonkit/express"; // or: import { toon } from "toonkit/fastify"
Function Signatures
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.
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
j and a must contain valid JSON. Use td for raw text that shouldn't be parsed.Complete Example
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
{
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โ nlstringโ snumberโ nbooleanโ bArrayโ aObjectโ j (JSON)
Example
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);
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.
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.
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.
import { toonToJson } from "toonkit"; const res = await fetch("/api/devices"); const text = await res.text(); const data = toonToJson(text);
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
import { toonFetch } from "toonkit"; const res = await toonFetch("https://localhost:3000/users"); console.log(res.data);
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 ...`.
const res = await toonFetch("https://localhost:3000/users", { token: "mytoken" }); // header => Authorization: Bearer mytoken
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`.
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.
await await toonFetch("https://localhost:3000/users", { method: "POST", headers: { "Content-Type": "application/json" }, data: { name: "Manoj" } });
Full example (headers + token + body)
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
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
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.
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.
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)
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.
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.
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.
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.
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:
Content-Type: text/plainExample TOON Body
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
// 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
- โ Keys repeated per row
- โ Nested braces & quotes
- โ Heavier for tables
- โ More to parse
- โ Keys declared once
- โ CSV-style rows
- โ Compact payloads
- โ Faster to parse
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.