Skip to content

TOON - Token-Oriented Object Notation

Token-Oriented Object Notation (TOON) is a compact and readable encoding of the JSON data model. Its layout can reduce the tokens needed to represent the data. TOON is a lossless representation of your existing JSON, for LLM input.

TOON takes the indentation structure of YAML for a nested object, and a CSV-style table layout for a uniform array. TOON works best for a uniform array of objects, that is several fields per row and the same structure in every item. Such an array is as compact as CSV, and its explicit structure helps an LLM parse and validate the data.

TOON sends the same data to an LLM in fewer tokens than JSON:

  • Cost reduction: fewer tokens give a lower API cost
  • Context efficiency: more room for content in the context window
  • Better parsing: the structured format helps an LLM read and use the data

TOON keeps the layout of CSV, which is simple and well known. It is also a lossless representation of JSON for a Large Language Model.

An object uses the YAML-style key: value notation, with a newline between the properties:

name: Alice
age: 30

This represents the same data as the JSON {"name": "Alice", "age": 30}.

A nested object uses indentation, with 2 spaces for each level:

user:
name: Bob
contact:
email: bob@ex.com

An array of primitives is inline, with a count:

[3]: 1,2,3

This is [1, 2, 3].

An array of objects with the same structure uses a CSV-style column format:

[2]{id,active}:
1,true
2,false

This is [{"id": 1, "active": true}, {"id": 2, "active": false}].

A column that holds objects with the same structure folds into the header:

orders[2]{id,customer{name,country}}:
1,Ada,DE
2,Bob,FR

This is [{"id": 1, "customer": {"name": "Ada", "country": "DE"}}, {"id": 2, "customer": {"name": "Bob", "country": "FR"}}].

An object whose values share the same structure uses a keyed header. The entry count carries a colon:

users[2:]{id,name}:
u1: 1,Ada
u2: 2,Bob

This is {"users": {"u1": {"id": 1, "name": "Ada"}, "u2": {"id": 2, "name": "Bob"}}}.

An array with mixed structures uses the dash notation:

[3]:
- a: 1
- a: 1
b: 2
- c: 3
  • Null values: null
  • Booleans: true or false
  • Empty arrays: key: []
  • Empty objects: key:
  • Strings with special characters: in quotes, with escapes, for example "He said \"hello\""
  • Strings that start with # or -: in quotes, for example tag: "#hello"
  • Keys outside letters, digits, _, and .: in quotes, for example "my-key": 1

The uc_ai_toon package converts JSON to the TOON format.

Use JSON_OBJECT to build a JSON object from one row. Then convert it to TOON:

DECLARE
l_json json_object_t;
l_toon clob;
BEGIN
SELECT json_object(
'employee_id' value employee_id,
'first_name' value first_name,
'last_name' value last_name,
'salary' value salary
)
INTO l_json
FROM employees
WHERE employee_id = 100;
l_toon := uc_ai_toon.to_toon(l_json);
dbms_output.put_line(l_toon);
-- Output:
-- employee_id: 100
-- first_name: Steven
-- last_name: King
-- salary: 24000
END;
/

Use JSON_ARRAYAGG to aggregate several rows into a JSON array:

DECLARE
l_json json_array_t;
l_toon clob;
BEGIN
SELECT json_arrayagg(
json_object(
'department_id' value department_id,
'department_name' value department_name,
'manager_id' value manager_id
)
)
INTO l_json
FROM departments
WHERE location_id = 1700;
l_toon := uc_ai_toon.to_toon(l_json);
dbms_output.put_line(l_toon);
-- Output (homogeneous array uses tabular format):
-- [7]{department_id,department_name,manager_id}:
-- 10,Administration,200
-- 30,Purchasing,114
-- 90,Executive,100
-- ...
END;
/

You can also pass a JSON string as a CLOB:

DECLARE
l_json_str clob;
l_toon clob;
BEGIN
-- Query returning JSON as string
SELECT json_object(
'count' value count(*),
'avg_salary' value round(avg(salary), 2)
returning clob)
INTO l_json_str
FROM employees;
l_toon := uc_ai_toon.to_toon(l_json_str);
dbms_output.put_line(l_toon);
-- Output:
-- count: 107
-- avg_salary: 6461.83
END;
/

This example sends database rows to an LLM as TOON, with few tokens:

DECLARE
l_products json_array_t;
l_toon_data clob;
l_result json_object_t;
l_response clob;
BEGIN
-- Build product data using JSON SQL functions
SELECT json_arrayagg(
json_object(
'id' value product_id,
'name' value product_name,
'price' value list_price,
'stock' value quantity_on_hand
)
ORDER BY product_name
)
INTO l_products
FROM products p
JOIN inventories i ON p.product_id = i.product_id
WHERE category_id = 1 -- Electronics
FETCH FIRST 10 ROWS ONLY;
-- Convert to TOON for token efficiency
l_toon_data := uc_ai_toon.to_toon(l_products);
-- Send to LLM with TOON-formatted context
l_result := uc_ai.generate_text(
p_system_prompt => 'You are analyzing product inventory data provided in TOON format (a compact JSON representation).',
p_user_prompt => 'Here is our current electronics inventory:' || chr(10) ||
l_toon_data || chr(10) || chr(10) ||
'Which products are running low on stock (less than 10 units)?',
p_provider => uc_ai.c_provider_openai,
p_model => uc_ai_openai.c_model_gpt_5_6_luna
);
l_response := l_result.get_clob('final_message');
dbms_output.put_line(l_response);
END;
/

TOON also encodes a complex nested structure. Use nested JSON_OBJECT and JSON_ARRAYAGG calls:

DECLARE
l_json json_object_t;
l_toon clob;
BEGIN
-- Build nested JSON with departments and their employees
SELECT json_object(
'department' value department_name,
'manager' value (
SELECT json_object(
'id' value e.employee_id,
'name' value e.first_name || ' ' || e.last_name
)
FROM employees e
WHERE e.employee_id = d.manager_id
),
'employee_count' value (
SELECT count(*)
FROM employees e
WHERE e.department_id = d.department_id
)
)
INTO l_json
FROM departments d
WHERE department_id = 90;
l_toon := uc_ai_toon.to_toon(l_json);
dbms_output.put_line(l_toon);
-- Output:
-- department: Executive
-- manager:
-- id: 100
-- name: Steven King
-- employee_count: 3
END;
/
function to_toon(p_json_object in json_object_t) return clob;

Converts a json_object_t to TOON format.

Parameters:

  • p_json_object: The JSON object to convert

Returns: a CLOB with the TOON representation

function to_toon(p_json_array in json_array_t) return clob;

Converts a json_array_t to TOON format.

Parameters:

  • p_json_array: The JSON array to convert

Returns: a CLOB with the TOON representation

function to_toon(p_json_string in clob) return clob;

Converts a JSON string (CLOB) to TOON format.

Parameters:

  • p_json_string: The JSON string to convert

Returns: a CLOB with the TOON representation

ScenarioRecommendation
Uniform arrays of objects (same structure)✅ Use TOON - the largest token saving
Tabular data from database queries✅ Use TOON - as compact as CSV
Simple flat objects✅ Use TOON - clearer than JSON
Deeply nested irregular structures⚠️ Use JSON - it can need fewer tokens
Non-uniform arrays with varied schemas⚠️ Use JSON - the TOON header adds no value
Data that the LLM returns❌ Use JSON - the standard format to parse