Skip to content

TOON Conversion

recipe JSON Schema C# toon conversion

This recipe demonstrates how to convert between JSON and TOON using the Corvus.Text.Json.Toon package. It covers parsing TOON into a pooled Corvus document, converting TOON to JSON, converting JSON to TOON, dotted-key path expansion, JSON key folding, and writing TOON directly to a UTF-8 buffer.

The Pattern

TOON is useful when you need a compact text representation of JSON-shaped data, especially for LLM prompts. It keeps the JSON data model, but removes repeated punctuation and can represent uniform object arrays as tables.

Use TOON at the prompt or transport boundary. Use JSON and generated Corvus types for validation, application logic, persistence, and API contracts.

Parsing TOON to a Document

The Corvus package parses TOON into the same pooled document model used by the rest of Corvus.Text.Json:

string toon = """
    name: Alice
    age: 30
    active: true
    scores[3]: 95,87,92
    """;

using ParsedJsonDocument<JsonElement> document = ToonDocument.Parse<JsonElement>(toon);
JsonElement root = document.RootElement;

Console.WriteLine($"Name:   {root.GetProperty("name").GetString()}");
Console.WriteLine($"Age:    {root.GetProperty("age").GetInt32()}");
Console.WriteLine($"Scores: {root.GetProperty("scores")}");

Output:

Name:   Alice
Age:    30
Scores: [95,87,92]

Converting TOON to JSON

Tabular TOON is converted back into standard JSON arrays of objects:

string toon = """
    [2]{id,name,score}:
      1,Alice,95
      2,Bob,87
    """;

string json = ToonDocument.ConvertToJsonString(toon);
Console.WriteLine(json);

Output:

[{"id":1,"name":"Alice","score":95},{"id":2,"name":"Bob","score":87}]

Converting JSON to TOON

Uniform arrays of objects are emitted as TOON tables automatically:

string json = """[{"id":1,"name":"Alice","score":95},{"id":2,"name":"Bob","score":87}]""";
string toon = ToonDocument.ConvertToToonString(json);
Console.WriteLine(toon);

Output:

[2]{id,name,score}:
  1,Alice,95
  2,Bob,87

Expanding Dotted Keys

By default, dotted keys remain literal JSON property names. Set ExpandPaths = ToonPathExpansion.Safe when you want unambiguous dotted paths to become nested JSON objects:

ToonReaderOptions options = new()
{
    ExpandPaths = ToonPathExpansion.Safe,
};

string json = ToonDocument.ConvertToJsonString(
    "user.name: Alice\nuser.age: 30",
    options);

JSON result:

{"user":{"name":"Alice","age":30}}

Folding JSON Keys

The reverse operation is key folding. Set KeyFolding = ToonKeyFolding.Safe and convert from a parsed JsonElement when you want the writer to fold nested object paths:

ToonWriterOptions options = new()
{
    KeyFolding = ToonKeyFolding.Safe,
};

using ParsedJsonDocument<JsonElement> document =
    ParsedJsonDocument<JsonElement>.Parse("""{"user":{"name":"Alice"},"active":true}""");

JsonElement root = document.RootElement;
string toon = ToonDocument.ConvertToToon(in root, options);

TOON result:

user.name: Alice
active: true

Writing to a UTF-8 Buffer

For hot paths, write TOON directly to an IBufferWriter<byte>:

ArrayBufferWriter<byte> buffer = new(256);
ToonDocument.ConvertToToon(
    """[{"id":1,"name":"Alice","score":95},{"id":2,"name":"Bob","score":87}]"""u8,
    buffer);

ReadOnlySpan<byte> utf8Toon = buffer.WrittenSpan;

This avoids creating the intermediate TOON string. It is the preferred form when the next step writes to a stream, socket, or other UTF-8 boundary.

Running the Example

cd docs/ExampleRecipes/041-Toon
dotnet run