toon

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 14 Imported by: 17

README

TOON for Go

Go Reference SPEC v4.4

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.

Installation

go get github.com/toon-format/toon-go

Usage

package 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

Specification

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 overflows float64 (e.g. 1e999) decodes as a string; on encode, integers beyond ±(2^53 − 1), *big.Int values included, become quoted decimal strings (§4)
  • Structs encode as objects keyed by their toon tags – toon:"name" renames, toon:"name,omitempty" skips zero values, toon:"-" skips the field, a field without a toon tag falls back to its json tag, and an untagged field uses its Go name; maps need string keys, time.Time and fmt.Stringer values become strings, and NaN and ±Inf become null (§3)
  • Decoded objects are map[string]any, so document key order is lost – on encode, toon.Object keeps 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.

Resources

  • 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

Contributing

See CONTRIBUTING.md for the development setup and pull request guidelines.

License

MIT License © 2025-PRESENT Bintang Pradana Erlangga Putra and Johann Schopplich

Documentation

Overview

Package toon encodes Go values to TOON (Token-Oriented Object Notation) and decodes TOON back.

Example
package 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)

	var out Payload
	if err := toon.UnmarshalString(encoded, &out); err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", out)
}
Output:
users[2]{id,name,role}:
  1,Ada,admin
  2,Bob,user
{Users:[{ID:1 Name:Ada Role:admin} {ID:2 Name:Bob Role:user}]}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Decode

func Decode(data []byte, opts ...DecoderOption) (any, error)

Decode parses the TOON document in data.

func DecodeString

func DecodeString(s string, opts ...DecoderOption) (any, error)

DecodeString parses the TOON document s.

func Marshal

func Marshal(v any, opts ...EncoderOption) ([]byte, error)

Marshal returns the TOON encoding of v.

func MarshalString

func MarshalString(v any, opts ...EncoderOption) (string, error)

MarshalString encodes v as a TOON document string.

func Unmarshal

func Unmarshal(data []byte, v any, opts ...DecoderOption) error

Unmarshal decodes the TOON document in data into v, which must be a non-nil pointer. Struct fields use `toon` struct tags, falling back to `json` tags, for naming, mirroring Marshal behavior.

func UnmarshalString

func UnmarshalString(s string, v any, opts ...DecoderOption) error

UnmarshalString decodes the TOON document in s into v.

Types

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

Decoder parses TOON documents into float64 numbers, map[string]any objects, and []any arrays. Go maps keep no insertion order, so document key order is lost. The zero value decodes with the default options. A Decoder is safe for concurrent use.

func NewDecoder

func NewDecoder(opts ...DecoderOption) *Decoder

NewDecoder constructs a Decoder with the given options.

func (*Decoder) Decode added in v0.2.0

func (d *Decoder) Decode(data []byte) (any, error)

Decode parses the provided TOON document. The bytes must be UTF-8; ill-formed sequences are an error in any mode.

func (*Decoder) DecodeString added in v0.2.0

func (d *Decoder) DecodeString(doc string) (any, error)

DecodeString parses the provided TOON document. The document must be UTF-8; ill-formed sequences are an error in any mode.

type DecoderOption

type DecoderOption func(*decoderOptions)

DecoderOption configures a Decoder.

func WithDecoderIndent

func WithDecoderIndent(spaces int) DecoderOption

WithDecoderIndent configures the expected indentation step. A value below 1 is ignored.

func WithStrictMode

func WithStrictMode(strict bool) DecoderOption

WithStrictMode toggles strict decoding. With false, the decoder accepts exactly five deviations: a declared length that doesn't match the content, duplicate keys and field names (the last one wins), tab or misaligned indentation (each tab one level, spaces floored), blank lines inside an array or keyed tabular object, and a block whose first line is indented too deep, which then sets the block's depth. Every other decoding error applies in both modes.

type Delimiter

type Delimiter rune

Delimiter identifies the character used to split field entries, inline array values, tabular row cells, and keyed entry-row cells.

const (
	// DelimiterComma is the default delimiter. It is omitted from brackets.
	DelimiterComma Delimiter = ','
	// DelimiterTab uses HTAB for delimiting values.
	DelimiterTab Delimiter = '\t'
	// DelimiterPipe uses the '|' character for delimiting values.
	DelimiterPipe Delimiter = '|'
)

func (Delimiter) String added in v0.2.0

func (d Delimiter) String() string

String returns "comma", "tab", or "pipe", or delimiter('x') for any other rune x.

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder serializes Go values as TOON documents. The zero value encodes with the default options. An Encoder is safe for concurrent use.

func NewEncoder

func NewEncoder(opts ...EncoderOption) *Encoder

NewEncoder constructs an Encoder using the supplied options.

func (*Encoder) Marshal added in v0.2.0

func (e *Encoder) Marshal(v any) ([]byte, error)

Marshal renders v as a TOON document.

func (*Encoder) MarshalString added in v0.2.0

func (e *Encoder) MarshalString(v any) (string, error)

MarshalString is equivalent to Marshal but returns a string.

type EncoderOption

type EncoderOption func(*encoderOptions)

EncoderOption configures an Encoder.

func WithDelimiter

func WithDelimiter(delimiter Delimiter) EncoderOption

WithDelimiter sets the delimiter that every emitted header declares. A value other than DelimiterComma, DelimiterTab, or DelimiterPipe is ignored.

func WithIndent

func WithIndent(spaces int) EncoderOption

WithIndent configures the number of spaces used per indentation level. A value below 1 is ignored.

func WithTimeFormatter

func WithTimeFormatter(formatter func(time.Time) string) EncoderOption

WithTimeFormatter specifies the formatter used for time.Time normalization. A nil formatter is ignored.

type Field

type Field struct {
	Key   string
	Value any
}

Field represents a single key/value pair in an ordered object.

type Object

type Object struct {
	Fields []Field
}

Object preserves the encounter order of its fields, ensuring deterministic emission by the encoder.

func NewObject

func NewObject(fields ...Field) Object

NewObject constructs an ordered Object from the provided key/value pairs.

func (Object) IsEmpty added in v0.2.0

func (o Object) IsEmpty() bool

IsEmpty reports whether the object has no fields.

func (Object) Len added in v0.2.0

func (o Object) Len() int

Len reports the number of fields.

Directories

Path Synopsis
internal
format
Package format implements the string, key, and number rendering rules of the TOON specification.
Package format implements the string, key, and number rendering rules of the TOON specification.
parse
Package parse implements the lexical helpers the TOON decoder needs: unescaping quoted tokens, scanning for unquoted characters, and splitting delimiter-separated cell sequences.
Package parse implements the lexical helpers the TOON decoder needs: unescaping quoted tokens, scanning for unquoted characters, and splitting delimiter-separated cell sequences.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址