TOON Implementation Tutorial: Step-by-Step Integration Guide
📅 December 17, 2025📖 Reading time: 13 minutesTutorial Guide
A comprehensive step-by-step guide for integrating TOON format into your applications. Learn how to convert between JSON and TOON, handle errors, and optimize for production use across JavaScript, Python, and Java.
Table of Contents
1. Overview & Setup
When to Use TOON
TOON is ideal for:
- APIs with high request volumes (savings on bandwidth/tokens)
- Mobile applications (reduced data usage)
- LLM integrations (token cost reduction)
- Real-time data streaming
- Caching and storage optimization
- Microservices communication
Prerequisites
- Basic understanding of JSON serialization
- Familiarity with your programming language
- Knowledge of your data structure
- Testing framework for your language
Installation Overview
TOON libraries are available for all major programming languages. Most are installable via package managers.
2. JavaScript/Node.js Implementation
Installation
npm install @toon/coreBasic Usage: JSON to TOON Conversion
import { toToon, fromToon } from '@toon/core';
// Create a JavaScript object
const userData = {
id: 1,
name: "Alice Johnson",
email: "alice@example.com",
isActive: true,
balance: 1250.50,
tags: ["premium", "verified"]
};
// Convert to TOON format
const toonData = toToon(userData);
console.log(toonData);
// Output: {id: 1, name: "Alice Johnson", email: "alice@example.com", isActive: b1, balance: 1250.50, tags: ["premium", "verified"]}
// Size comparison
console.log('JSON size:', JSON.stringify(userData).length, 'bytes');
console.log('TOON size:', toonData.length, 'bytes');
// Output: JSON size: 127 bytes
// TOON size: 88 bytes (30% reduction)
// Convert back to JavaScript object
const restored = fromToon(toonData);
console.log(restored);
// Output: { id: 1, name: "Alice Johnson", ... }API Response Optimization
Convert API responses to reduce bandwidth:
// server.js - Express middleware to convert responses
import express from 'express';
import { toToon, fromToon } from '@toon/core';
const app = express();
// Middleware to detect TOON preference
app.use((req, res, next) => {
res.locals.useToon = req.headers['accept-encoding']?.includes('toon') ||
req.query.format === 'toon';
next();
});
// API endpoint
app.get('/api/users/:id', async (req, res) => {
const user = await fetchUserFromDatabase(req.params.id);
if (res.locals.useToon) {
res.setHeader('Content-Type', 'application/toon');
res.setHeader('Content-Encoding', 'toon');
res.send(toToon(user));
} else {
res.json(user);
}
});
// Client-side usage
async function fetchUser(userId) {
const response = await fetch(`/api/users/${userId}`, {
headers: { 'Accept-Encoding': 'toon' }
});
const data = response.headers.get('content-encoding') === 'toon'
? fromToon(await response.text())
: await response.json();
return data;
}Streaming Large Datasets
import { createReadStream, createWriteStream } from 'fs';
import { Transform } from 'stream';
import { toToon, fromToon } from '@toon/core';
// Convert a JSON file to TOON
function convertJsonToToon(inputFile, outputFile) {
const transformer = new Transform({
transform(chunk, encoding, callback) {
try {
const lines = chunk.toString().split('\n');
const converted = lines
.map(line => line.trim())
.filter(line => line && line !== '[' && line !== ']' && line !== ',')
.map(line => {
const json = JSON.parse(line);
return toToon(json);
})
.join('\n');
callback(null, converted);
} catch (err) {
callback(err);
}
}
});
createReadStream(inputFile)
.pipe(transformer)
.pipe(createWriteStream(outputFile))
.on('finish', () => console.log('Conversion complete'));
}3. Python Implementation
Installation
pip install toonBasic Usage
import toon
import json
# Create a dictionary
user_data = {
'id': 1,
'name': 'Alice Johnson',
'email': 'alice@example.com',
'is_active': True,
'balance': 1250.50,
'tags': ['premium', 'verified']
}
# Convert to TOON
toon_data = toon.encode(user_data)
print(f'TOON: {toon_data}')
# Output: {id: 1, name: "Alice Johnson", email: "alice@example.com", is_active: b1, balance: 1250.5, tags: ["premium", "verified"]}
# Size comparison
json_size = len(json.dumps(user_data))
toon_size = len(toon_data)
print(f'JSON: {json_size} bytes, TOON: {toon_size} bytes')
print(f'Reduction: {(1 - toon_size/json_size) * 100:.1f}%')
# Convert back to dict
restored = toon.decode(toon_data)
print(restored)
print(restored == user_data) # TrueDjango/FastAPI Integration
# FastAPI example
from fastapi import FastAPI, Header
from fastapi.responses import Response
import toon
import json
app = FastAPI()
@app.get("/api/users/{user_id}")
async def get_user(user_id: int, accept_encoding: str = Header(None)):
user_data = {
'id': user_id,
'name': 'Alice',
'email': f'user{user_id}@example.com'
}
if accept_encoding and 'toon' in accept_encoding:
toon_encoded = toon.encode(user_data)
return Response(
content=toon_encoded,
media_type='application/toon',
headers={'Content-Encoding': 'toon'}
)
else:
return user_data
# Client usage
import requests
response = requests.get(
'http://localhost:8000/api/users/1',
headers={'Accept-Encoding': 'toon'}
)
if response.headers.get('Content-Encoding') == 'toon':
user_data = toon.decode(response.text)
else:
user_data = response.json()
print(user_data)Batch Processing with Pandas
import pandas as pd
import toon
import os
# Read CSV into DataFrame
df = pd.read_csv('users.csv')
# Convert each row to TOON and save
def convert_to_toon(row):
return toon.encode(row.to_dict())
df['toon_data'] = df.apply(convert_to_toon, axis=1)
# Save TOON-encoded data
df[['id', 'toon_data']].to_csv('users_toon.csv', index=False)
# Check size reduction
original_size = os.path.getsize('users.csv')
toon_size = os.path.getsize('users_toon.csv')
print(f'Original: {original_size} bytes')
print(f'TOON: {toon_size} bytes')
print(f'Reduction: {(1 - toon_size/original_size) * 100:.1f}%')4. Java Implementation
Maven Setup
<!-- pom.xml -->
<dependency>
<groupId>com.toon</groupId>
<artifactId>toon-core</artifactId>
<version>1.0.0</version>
</dependency>Basic Usage
import com.toon.*;
import java.util.*;
public class ToonExample {
public static void main(String[] args) {
// Create a Map (similar to JSON object)
Map<String, Object> userData = new HashMap<>();
userData.put("id", 1);
userData.put("name", "Alice Johnson");
userData.put("email", "alice@example.com");
userData.put("isActive", true);
userData.put("balance", 1250.50);
userData.put("tags", Arrays.asList("premium", "verified"));
// Convert to TOON
ToonEncoder encoder = new ToonEncoder();
String toonData = encoder.encode(userData);
System.out.println("TOON: " + toonData);
// Size comparison
String jsonData = new ObjectMapper().writeValueAsString(userData);
System.out.println("JSON size: " + jsonData.length() + " bytes");
System.out.println("TOON size: " + toonData.length() + " bytes");
System.out.println("Reduction: " +
String.format("%.1f%%", (1 - (double)toonData.length() / jsonData.length()) * 100));
// Convert back
ToonDecoder decoder = new ToonDecoder();
Map<String, Object> restored = decoder.decode(toonData);
System.out.println("Restored: " + restored);
}
}Spring Boot REST API
@RestController
@RequestMapping("/api")
public class UserController {
private final UserService userService;
private final ToonEncoder encoder;
private final ToonDecoder decoder;
@GetMapping("/users/{id}")
public ResponseEntity<?> getUser(
@PathVariable Long id,
@RequestHeader(value = "Accept-Encoding", required = false) String acceptEncoding) {
User user = userService.findById(id);
if (acceptEncoding != null && acceptEncoding.contains("toon")) {
String toonData = encoder.encode(user);
return ResponseEntity.ok()
.header("Content-Encoding", "toon")
.contentType(MediaType.valueOf("application/toon"))
.body(toonData);
} else {
return ResponseEntity.ok(user);
}
}
}5. Error Handling & Debugging
Common Issues and Solutions
Issue 1: Invalid TOON Format
// JavaScript error handling
import { fromToon } from '@toon/core';
try {
const invalidToon = '{id: 1, name: "invalid}'; // Missing closing quote
const data = fromToon(invalidToon);
} catch (err) {
console.error('Parse error:', err.message);
// Output: Parse error: Unexpected end of input at position 30
}
// Validate TOON before parsing
function safeParseToon(toonData) {
try {
if (!toonData || typeof toonData !== 'string') {
throw new Error('TOON data must be a non-empty string');
}
return fromToon(toonData);
} catch (err) {
console.error('Failed to parse TOON:', err.message);
return null;
}
}Issue 2: Type Conversion Errors
# Python example
import toon
# ❌ Error: Mixed types in array
try:
bad_data = {'items': [1, 'two', True]} # Mixed types
encoded = toon.encode(bad_data)
except TypeError as e:
print(f'Type error: {e}')
# ✅ Solution: Use consistent types
good_data = {
'int_items': [1, 2, 3],
'str_items': ['one', 'two', 'three'],
'bool_items': [True, False, True]
}
encoded = toon.encode(good_data)Issue 3: Large Payload Handling
// JavaScript streaming for large payloads
import { toToon } from '@toon/core';
// ❌ Bad: Loading entire file into memory
const largeData = JSON.parse(fs.readFileSync('large-file.json'));
const encoded = toToon(largeData); // May cause OOM
// ✅ Good: Process in chunks
import { createReadStream, createWriteStream } from 'fs';
function processLargeFile(inputPath, outputPath) {
let buffer = '';
let itemCount = 0;
createReadStream(inputPath, { encoding: 'utf8' })
.on('data', (chunk) => {
buffer += chunk;
const lines = buffer.split('\n');
buffer = lines.pop(); // Keep incomplete line in buffer
lines.forEach(line => {
try {
const obj = JSON.parse(line);
const toonEncoded = toToon(obj);
itemCount++;
console.log(`Processed ${itemCount} items`);
} catch (err) {
console.error(`Error on line: ${line}`);
}
});
})
.on('end', () => {
if (buffer) {
const obj = JSON.parse(buffer);
const toonEncoded = toToon(obj);
itemCount++;
}
console.log(`Total processed: ${itemCount} items`);
});
}Debugging Techniques
// JavaScript debugging helpers
import { toToon, fromToon } from '@toon/core';
function debugConversion(data) {
console.log('Original data:', data);
const jsonStr = JSON.stringify(data);
const toonStr = toToon(data);
console.log('JSON:', jsonStr);
console.log('TOON:', toonStr);
console.log('Size: JSON=' + jsonStr.length + ', TOON=' + toonStr.length);
console.log('Reduction:', ((1 - toonStr.length/jsonStr.length) * 100).toFixed(1) + '%');
const restored = fromToon(toonStr);
console.log('Restored:', restored);
console.log('Match:', JSON.stringify(data) === JSON.stringify(restored));
}
debugConversion({
id: 1,
name: "Test",
active: true
});6. Best Practices & Performance Tips
Performance Optimization
- Cache Encoders/Decoders: Create encoder/decoder instances once and reuse them
- Use Streaming for Large Files: Process data in chunks to avoid memory issues
- Profile Before and After: Measure actual savings in your environment
- Consider Compression: Combine TOON with gzip for additional 30-50% reduction
- Monitor Production: Track conversion times and error rates
Migration Strategy
- Phase 1 - Testing: Run TOON alongside JSON in non-production for 1-2 weeks
- Phase 2 - Canary: Enable TOON for 5-10% of traffic to detect issues
- Phase 3 - Gradual Rollout: Increase to 25%, 50%, 100% over 1-2 weeks
- Phase 4 - Monitoring: Track performance metrics for 1 month
- Phase 5 - Full Migration: Switch all traffic to TOON and deprecate JSON
Backward Compatibility
Support both JSON and TOON during transition:
// Utility to handle both formats
function parseData(data, format = 'auto') {
if (format === 'toon' || (format === 'auto' && data.includes(': '))) {
return fromToon(data);
} else if (format === 'json' || (format === 'auto' && data.startsWith('{'))) {
return JSON.parse(data);
} else {
throw new Error(`Unknown format: ${format}`);
}
}
// Usage
const jsonData = '{"id": 1, "name": "Alice"}';
const toonData = '{id: 1, name: "Alice"}';
console.log(parseData(jsonData)); // Works
console.log(parseData(toonData)); // WorksMonitoring & Metrics
// Monitoring helper
class ToonMetrics {
constructor() {
this.conversions = 0;
this.totalJsonSize = 0;
this.totalToonSize = 0;
this.errors = 0;
}
recordConversion(jsonSize, toonSize) {
this.conversions++;
this.totalJsonSize += jsonSize;
this.totalToonSize += toonSize;
}
recordError() {
this.errors++;
}
getStats() {
return {
conversions: this.conversions,
averageJsonSize: this.totalJsonSize / this.conversions,
averageToonSize: this.totalToonSize / this.conversions,
averageReduction: (1 - this.totalToonSize / this.totalJsonSize) * 100,
errors: this.errors,
errorRate: (this.errors / this.conversions * 100).toFixed(2) + '%'
};
}
}
const metrics = new ToonMetrics();
// Track usage and report regularlyConclusion
Integrating TOON into your application is straightforward with language-specific libraries available for JavaScript, Python, Java, and more. By following this tutorial:
- You can reduce payload sizes by 35-50%
- Achieve 37% faster parsing speeds
- Maintain backward compatibility during migration
- Handle errors gracefully with proper validation
- Monitor performance improvements in production
Ready to implement TOON?
Try our interactive converter to see real-world compression gains with your data.
Try the Converter Now