DEV Community

Cover image for Build a Bi‑Directional TOON Parser in C#: Convert TOON JSON with Ease
David Au Yeung
David Au Yeung

Posted on

Build a Bi‑Directional TOON Parser in C#: Convert TOON JSON with Ease

Introduction

Toon (Token-Oriented Object Notation) is a newly promoted format designed specifically for saving LLM tokens.
It is compact, human-readable, extremely lightweight, and optimized for AI workflows where every token counts.

Compared to JSON, TOON reduces noise, avoids unnecessary braces/quotes, and stores structured data in a flat and token-efficient way. With the rise of AI prompting and agent-based architectures, TOON is quickly becoming a favorite among developers and ML engineers.

In this guide, you will learn how to build a complete bi-directional TOON parser in C#:
✔ TOON → JSON
✔ JSON → TOON
✔ Fully automatic, scalable, and easy to extend

This works on .NET 6, .NET 8, and .NET 9, and requires no external dependencies.

Step 1: Create the ToonConverter Class

We will build a utility class that contains:

ParseToon() converts TOON into a C# dictionary
ToonToJson() converts TOON into JSON
JsonToToon() converts JSON back into TOON

Create a new file named ToonConverter.cs and insert the following code:

using System.Text.Json;
using System.Text.Json.Nodes;

public static class ToonConverter
{
    // --------------------------------------
    // 1. TOON → OBJECT (Dictionary)
    // --------------------------------------
    public static Dictionary<string, List<Dictionary<string, string>>> ParseToon(string toon)
    {
        var result = new Dictionary<string, List<Dictionary<string, string>>>();
        var lines = toon.Split('\n', StringSplitOptions.RemoveEmptyEntries)
                        .Select(x => x.Trim()).ToList();

        int i = 0;

        while (i < lines.Count)
        {
            if (!lines[i].Contains("{"))
            {
                i++;
                continue;
            }

            string header = lines[i];
            i++;

            string name = header[..header.IndexOf("[")];

            string fieldBlock = header[(header.IndexOf("{") + 1)..header.IndexOf("}")];

            string[] fields = fieldBlock.Split(',')
                                        .Select(f => f.Trim()).ToArray();

            var rows = new List<Dictionary<string, string>>();

            while (i < lines.Count && !lines[i].Contains("{"))
            {
                if (string.IsNullOrWhiteSpace(lines[i]))
                {
                    i++;
                    continue;
                }

                var vals = lines[i].Split(",").Select(v => v.Trim()).ToArray();

                var obj = new Dictionary<string, string>();
                for (int f = 0; f < fields.Length; f++)
                    obj[fields[f]] = vals[f];

                rows.Add(obj);
                i++;
            }

            result[name] = rows;
        }

        return result;
    }

    // --------------------------------------
    // 2. TOON → JSON
    // --------------------------------------
    public static string ToonToJson(string toon)
    {
        var obj = ParseToon(toon);
        return JsonSerializer.Serialize(obj, new JsonSerializerOptions { WriteIndented = true });
    }

    // --------------------------------------
    // 3. JSON → TOON
    // --------------------------------------
    public static string JsonToToon(string json)
    {
        JsonNode root = JsonNode.Parse(json)!;

        var sb = new System.Text.StringBuilder();

        foreach (var block in root.AsObject())
        {
            string name = block.Key;

            if (block.Value is not JsonArray arr)
                continue;

            if (arr.Count == 0)
                continue;

            // Extract fields from first object
            var first = arr[0]!.AsObject();
            var fields = first.Select(x => x.Key).ToList();

            sb.Append($"{name}[{arr.Count}]{{");
            sb.Append(string.Join(",", fields));
            sb.AppendLine("}:");

            // Add rows
            foreach (JsonNode? row in arr)
            {
                var obj = row!.AsObject();
                sb.AppendLine(string.Join(",", fields.Select(f => obj[f]!.ToString())));
            }

            sb.AppendLine();
        }

        return sb.ToString().Trim();
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Try TOON → JSON Conversion

Example TOON format:

Characters[3]{Name,Age,Role}:
Alice,25,Warrior
Bob,30,Mage
Charlie,22,Rogue

Items[2]{ItemName,Quantity,Price}:
Sword,5,100
Potion,20,10

Convert it:

string toonData = @"
 Characters[3]{Name,Age,Role}:
 Alice,25,Warrior
 Bob,30,Mage
 Charlie,22,Rogue

 Items[2]{ItemName,Quantity,Price}:
 Sword,5,100
 Potion,20,10
";

string json = ToonConverter.ToonToJson(toonData);
Console.WriteLine(json);
Enter fullscreen mode Exit fullscreen mode

Output:

Clean, structured, ready for APIs or storage.

Step 3: JSON → TOON Conversion

Given JSON:

{
  "Characters": [
    {
      "Name": "Alice",
      "Age": "25",
      "Role": "Warrior"
    },
    {
      "Name": "Bob",
      "Age": "30",
      "Role": "Mage"
    },
    {
      "Name": "Charlie",
      "Age": "22",
      "Role": "Rogue"
    }
  ],
  "Items": [
    {
      "ItemName": "Sword",
      "Quantity": "5",
      "Price": "100"
    },
    {
      "ItemName": "Potion",
      "Quantity": "20",
      "Price": "10"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Convert it back:

string toonFromJson = ToonConverter.JsonToToon(json);
Console.WriteLine(toonFromJson);
Enter fullscreen mode Exit fullscreen mode

Output:

Perfect round-trip.

Step 4: Integrate Into Your Project

This parser works great for:

• AI agents
• LLM prompt optimization
• Memory-efficient data transfer
• Chat-based structured data
• Internal DSLs
• Config files for AI workflows

Because TOON is extremely tiny, your prompts stay clean and token-friendly.

Summary

In this article, we learned how to:

✔ Create a lightweight bi-directional TOON parser
✔ Convert TOON → JSON
✔ Convert JSON → TOON
✔ Support multi-block, multi-row structured data

TOON is fast becoming the JSON‑alternative for the AI era, and having your own parser gives you maximum flexibility for future workflows.

If you enjoyed this guide, follow me on DEV for more C#, .NET, and AI‑related tutorials.

Love C# & AI!

Top comments (3)

Collapse
 
bartek_ceed9ec625d8ec89c3 profile image
Bartek

Super clean write-up - love how you break down the entire TOON → JSON → TOON pipeline in a way that feels practical, not theoretical.
JSON2TOON - definitely try this tool if you want to see TOON parsing in action with live data.

Collapse
 
nube_colectiva_nc profile image
Nube Colectiva

Interesting solution 👍🏼, I think that if this data format starts to be used more, programming languages will develop native methods to do it.

Collapse
 
auyeungdavid_2847435260 profile image
David Au Yeung

Yes, mate, I hope so.

Hopefully this solution can help a little during this transitional period.