eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Overview

JSON is the standard format for exchanging structured data between systems. But when we send JSON to large language models (LLMs), a surprising amount of the token budget goes toward syntax, including braces, brackets, quotes, and repeated key names rather than actual data.

TOON (Token-Oriented Object Notation) is a compact, human-readable format that encodes the same data model as JSON while using significantly fewer tokens. It replaces JSON’s punctuation-heavy syntax with indentation and, for uniform collections, a tabular layout that states field names once and streams values row by row.

In this tutorial, we’ll survey the available Java TOON libraries, use json-io for working examples of serializing and deserializing TOON, compare token counts between the formats, and discuss where TOON delivers the most value.

2. What Is TOON?

TOON encodes the same primitives, objects, and arrays as JSON. The differences are syntactic:

  • Objects use key: value pairs separated by newlines and indentation, not braces
  • Arrays use [N]: length-prefixed lists instead of brackets
  • Tabular arrays declare field names once in a header row, then list values in CSV-like rows
  • Quoting is minimal — strings only need quotes when they contain structural characters

Here is the same data in JSON and TOON:

JSON:

[
  {"name": "Alice", "age": 28, "department": "Engineering"},
  {"name": "Bob", "age": 34, "department": "Marketing"},
  {"name": "Charlie", "age": 22, "department": "Sales"}
]

TOON (tabular):

[3]{name,age,department}:
  Alice,28,Engineering
  Bob,34,Marketing
  Charlie,22,Sales

The tabular format states name, age, and department once in the header. Each subsequent row contains only the values. As the number of rows grows, the savings accumulate because JSON repeats every key name on every object.

For a single object, TOON uses a YAML-like key-value layout:

name: Alice
age: 28
department: Engineering

The full specification lives at toonformat.dev.

3. Java Libraries for TOON

The TOON ecosystem includes implementations in over 25 languages. For Java, there are two libraries available today:

Library Maven Coordinates Java Version Status Notes
JToon dev.toonformat:jtoon:1.0.8 Java 17+ Beta Official community implementation. Jackson annotation support. Focused on spec compliance.
json-io com.cedarsoftware:json-io:4.98.0 Java 8+ Stable Mature JSON library with TOON read/write. Jackson annotation support. Single runtime dependency (java-util).

Both libraries support TOON encoding and decoding with tabular arrays. JToon is the official community Java implementation, built specifically for TOON with Jackson integration. json-io is a mature JSON serialization library that added TOON as an additional output format alongside JSON.

We can find the latest version of json-io on Maven Central. For the examples in this tutorial, we’ll use json-io because it supports Java 8 through 24, allowing the widest range of projects to follow along:

<dependency>
    <groupId>com.cedarsoftware</groupId>
    <artifactId>json-io</artifactId>
    <version>4.98.0</version>
</dependency>

4. Writing Java Objects to TOON

4.1. Single Objects

We can convert any Java object to TOON with JsonIo.toToon():

Person person = new Person("Alice", 28, "Engineering");

String toon = JsonIo.toToon(person, null);

This produces:

name: Alice
age: 28
department: Engineering

The second parameter accepts a WriteOptions instance for controlling output. Passing null uses defaults.

4.2. Collections: The Tabular Format

The tabular format is where TOON delivers its biggest advantage. When we serialize a list of objects that share the same fields, json-io automatically uses the compact row-per-object layout:

List<Employee> employees = Arrays.asList(
    new Employee("Alice Johnson", 28, "Engineering", 95000),
    new Employee("Bob Smith", 34, "Marketing", 78000),
    new Employee("Charlie Brown", 22, "Engineering", 72000)
);

String toon = JsonIo.toToon(employees, null);

Output:

[3]{name,age,department,salary}:
  Alice Johnson,28,Engineering,95000
  Bob Smith,34,Marketing,78000
  Charlie Brown,22,Engineering,72000

The [3] declares the array length. The {name,age,department,salary} header names the columns. Each row contains only comma-separated values. The key names name, age, department, and salary appear once rather than three times.

If we prefer the expanded list format, one key-value pair per line, we can enable prettyPrint using the builder pattern:

WriteOptions options = new WriteOptionsBuilder().prettyPrint(true).build();
String toon = JsonIo.toToon(employees, options);

This produces the verbose form:

[3]:
  - name: Alice Johnson
    age: 28
    department: Engineering
    salary: 95000
  - name: Bob Smith
    age: 34
    department: Marketing
    salary: 78000
  - name: Charlie Brown
    age: 22
    department: Engineering
    salary: 72000

The default tabular layout is preferred for LLM interactions because it minimizes tokens. The expanded prettyPrint form repeats every key name on every object, so it uses roughly the same number of tokens as JSON and the savings disappear.

4.3. Nested Structures

TOON handles nesting naturally through indentation. Here, a company contains departments stored in a LinkedHashMap, each with a list of members:

Map<String, Object> eng = new LinkedHashMap<>();
eng.put("name", "Engineering");
eng.put("members", Arrays.asList(
  new Person("Alice", 28, "Engineering"),
  new Person("Bob", 34, "Engineering"),
  new Person("Charlie", 22, "Engineering")));

Map<String, Object> company = new LinkedHashMap<>();
company.put("name", "Acme Corp");
company.put("founded", 2010);
company.put("departments", Arrays.asList(eng, marketing, sales));  // marketing and sales built similarly

String toon = JsonIo.toToon(company, null);

Output:

name: Acme Corp
founded: 2010
departments[3]:
  - name: Engineering
    members[3]{name,age,department}:
      Alice,28,Engineering
      Bob,34,Engineering
      Charlie,22,Engineering
  - name: Marketing
    members[3]{name,age,department}:
      Eve,29,Marketing
      Frank,45,Marketing
      Grace,27,Marketing
  - name: Sales
    members[3]{name,age,department}:
      Hank,38,Sales
      Iris,33,Sales
      Jack,41,Sales

Notice that the inner members arrays use tabular format automatically. The outer departments array uses the expanded format because each department contains nested structured data, while the inner members arrays qualify for tabular format since their fields are all scalar values.

json-io applies this optimization at every level of the document: any array whose elements contain only scalar fields is automatically rendered in tabular format, regardless of nesting depth. In this example, each of the three members arrays gets its own column header and compact rows. This mix of key-value pairs and tabular rows within a single document is something CSV cannot express.

5. Reading TOON Back to Java

Parsing TOON is the mirror of writing it. We can deserialize to typed Java objects:

String toon = "name: Alice\nage: 28\ndepartment: Engineering";

Person person = JsonIo.fromToon(toon, null).asClass(Person.class);

assertEquals("Alice", person.getName());
assertEquals(28, person.getAge());
assertEquals("Engineering", person.getDepartment());

For generic collection types, we use TypeHolder to work around type erasure:

String toon = "[2]{name,age,department}:\n  Alice,28,Engineering\n  Bob,34,Marketing";

List<Person> people = JsonIo.fromToon(toon, null)
  .asType(new TypeHolder<List<Person>>(){});

assertEquals(2, people.size());
assertEquals("Alice", people.get(0).getName());
assertEquals("Engineering", people.get(0).getDepartment());

When we don’t have Java classes available, for example in middleware or log processing, we can parse to Maps:

Map<String, Object> map = JsonIo.fromToonToMaps(toon).asClass(Map.class);

6. Token Efficiency: Measuring the Difference

The motivation behind TOON is reducing token consumption when structured data is sent to LLMs. Rather than comparing character counts, which would be misleading since the formats have fundamentally different syntax density, we measure actual BPE (Byte Pair Encoding) tokens using the same tokenizer that GPT-5 uses.

We use jtokkit, a Java implementation of OpenAI’s tokenizer, with the o200k_base encoding:

EncodingRegistry registry = Encodings.newDefaultEncodingRegistry();
Encoding encoding = registry.getEncoding(EncodingType.O200K_BASE);

int jsonTokens = encoding.countTokens(jsonString);
int toonTokens = encoding.countTokens(toonString);

Here are the results across several dataset sizes, serializing uniform lists of Employee objects (name, age, department, salary):

Dataset JSON Tokens TOON Tokens Savings
3 items 46 35 24%
10 items 206 121 41%
20 items 412 231 44%
25 items (products, 5 fields) 680 459 33%

The savings grow with collection size because JSON repeats every key name on every object, while TOON states them once. At 20 items with 4 fields, we save 44% of the tokens.

For a single object, the savings are modest (about 5%) since there is no key repetition to eliminate. For nested structures with small embedded arrays, the savings are also modest (about 3-5%) but the inner arrays still benefit from tabular format.

6.1. How Does TOON Compare to CSV?

A fair question: if we’re sending flat tabular data, why not just use CSV?

For purely flat data, CSV uses slightly fewer tokens than TOON: about 6% fewer in our benchmarks. The overhead comes from TOON’s [N]{fields}: header and two-space indentation on each row.

But CSV cannot represent nested data. When we tried encoding the company-with-departments structure as CSV, we had to denormalize, repeating “Acme Corp” and “2010” on every row, which used more tokens than both TOON and JSON.

Format Flat Data (20 rows) Nested Data
JSON 413 tokens 150 tokens
TOON 231 tokens 141 tokens
CSV 217 tokens 167 tokens (denormalized)

TOON occupies a practical middle ground: within 6% of CSV’s token efficiency for flat data, but it also handles the nesting and mixed structures that real-world APIs produce.

In agentic and tool-calling workflows, structured data often accounts for the majority of input tokens. A 30-40% reduction on that portion means lower API costs (providers charge per token) and a more effective context window, fitting more data into the same 128K or 200K window without truncation. A Java application using json-io can switch from JsonIo.toJson() to JsonIo.toToon() without any infrastructure changes.

7. Spring AI Integration

For projects using Spring AI, json-io provides a separate starter that automatically converts tool call results to TOON before they reach the LLM. We add one dependency:

<dependency>
    <groupId>com.cedarsoftware</groupId>
    <artifactId>json-io-spring-ai-toon</artifactId>
    <version>4.98.0</version>
</dependency>

Then we annotate any tool method with the ToonToolCallResultConverter:

@Tool(description = "Look up employees by department",
      resultConverter = ToonToolCallResultConverter.class)
List<Employee> findByDepartment(String department) {
    return employeeRepository.findByDepartment(department);
}

When Spring AI calls this tool and passes the result back to the LLM, the converter serializes the employee list to TOON’s tabular format, the same compact layout we saw in Section 4.2. The LLM receives fewer tokens without any changes to the tool’s business logic.

8. When to Use TOON

TOON isn’t a universal replacement for JSON. Here’s where it fits:

Use TOON when:

  • Sending structured data to LLMs (tool results, RAG payloads, data analysis contexts)
  • Working with collections of uniform objects (the tabular format’s sweet spot)
  • Token cost or context window pressure is a concern
  • Data has a mix of flat and nested structure

Stick with JSON when:

  • Communicating between services (REST APIs, message queues) where every consumer expects JSON
  • The data consumer is not an LLM
  • Schema validation or JSON Schema tooling is required
  • The data is purely flat with no nesting. CSV may be even more efficient.

TOON encodes the same data model as JSON, and json-io can write any object graph to either format. JSON’s advantage is its ecosystem: virtually every language, framework, and tool speaks JSON natively, and standards like JSON Schema provide validation infrastructure that TOON does not yet have. Where that ecosystem matters, REST APIs, message queues, configuration files, JSON is the natural choice. Where token efficiency matters: LLM tool results, RAG payloads, agentic workflows, TOON delivers measurable savings with no loss of expressiveness.

9. Conclusion

In this article, we surveyed the Java TOON libraries available today: JToon and json-io, and used json-io to serialize Java objects to TOON, measure the token savings against JSON using OpenAI’s BPE tokenizer, and integrate TOON into Spring AI tool calls. For collections of uniform objects, TOON’s tabular format delivers 30-44% fewer tokens compared to clean JSON. It achieves near-CSV efficiency for flat data while also handling the nested structures that CSV cannot represent.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)