Encodes Go values to TOON (Token-Oriented Object Notation) and decodes TOON back. TOON is a compact, indentation-based encoding of the JSON data model for LLM input.
go get github.com/toon-format/toon-gopackage main
import (
"fmt"
"github.com/toon-format/toon-go"
)
type User struct {
ID int `toon:"id"`
Name string `toon:"name"`
Role string `toon:"role"`
}
type Payload struct {
Users []User `toon:"users"`
}
func main() {
in := Payload{Users: []User{{1, "Ada", "admin"}, {2, "Bob", "user"}}}
encoded, err := toon.MarshalString(in)
if err != nil {
panic(err)
}
fmt.Println(encoded)
// users[2]{id,name,role}:
// 1,Ada,admin
// 2,Bob,user
var out Payload
if err := toon.UnmarshalString(encoded, &out); err != nil {
panic(err)
}
fmt.Printf("%+v\n", out)
// {Users:[{ID:1 Name:Ada Role:admin} {ID:2 Name:Bob Role:user}]}
}Without a destination type, Decode and DecodeString return map[string]any, []any, and primitives. Pass encoder options to Marshal and decoder options to Unmarshal or Decode:
| Option | Default | Description |
|---|---|---|
WithIndent(n) |
2 |
Spaces per indentation level when encoding |
WithDelimiter(d) |
DelimiterComma |
Delimiter for array values and tabular rows: DelimiterComma, DelimiterTab, or DelimiterPipe |
WithTimeFormatter(f) |
RFC 3339 in UTC | Formats time.Time values |
WithStrictMode(b) |
true |
false accepts declared counts that don't match, duplicate keys (the last wins), tab or misaligned indentation, blank lines inside an array or keyed tabular object, and a block indented too deep; every other decoding error stays |
WithDecoderIndent(n) |
2 |
Expected spaces per indentation level when decoding |
Targets TOON spec v4.4, and the test suite runs the spec's conformance fixtures.
- Numbers decode to
float64– integers beyond 2^53 lose precision and a token that overflowsfloat64(e.g.1e999) decodes as a string; on encode, integers beyond ±(2^53 − 1),*big.Intvalues included, become quoted decimal strings (§4) - Structs encode as objects keyed by their
toontags –toon:"name"renames,toon:"name,omitempty"skips zero values,toon:"-"skips the field, a field without atoontag falls back to itsjsontag, and an untagged field uses its Go name; maps need string keys,time.Timeandfmt.Stringervalues become strings, andNaNand±Infbecomenull(§3) - Decoded objects are
map[string]any, so document key order is lost – on encode,toon.Objectkeeps its field order and Go maps are written in sorted key order (§2)
Releases follow SemVer: a new spec MINOR version ships as a MINOR release, even when it changes how hand-written input decodes, and a MAJOR release means an API break or a new spec MAJOR version.
- Specification: SPEC.md – Normative rules and conformance checklists
- Format Overview: toonformat.dev – Every form with examples
- Other Implementations: toonformat.dev – TOON in other languages
- API Reference: pkg.go.dev – Every exported function and option
See CONTRIBUTING.md for the development setup and pull request guidelines.
MIT License © 2025-PRESENT Bintang Pradana Erlangga Putra and Johann Schopplich