jsonlite

package module
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Feb 2, 2026 License: MIT Imports: 14 Imported by: 1

README

jsonlite

Go Reference

A lightweight JSON parser for Go, optimized for performance through careful memory management.

Motivation

Go's standard encoding/json package is designed for marshaling and unmarshaling into Go structs. This works well when you know the schema ahead of time, but becomes awkward when you need to traverse arbitrary JSON structures—you end up with map[string]interface{} and type assertions everywhere.

Packages like github.com/tidwall/gjson solve this with path-based queries, but they re-scan the input for each query. If you're recursively walking a JSON document, you pay the parsing cost repeatedly.

jsonlite takes a different approach: parse once, traverse many times. The parser builds a lightweight in-memory index of the entire document in a single pass. Once parsed, you can navigate the structure freely without re-parsing.

Design

The core insight is that most JSON strings don't contain escape sequences. When a string like "hello" appears in the input, we don't need to copy it—we can just point directly into the original input buffer. Only strings with escapes (like "hello\nworld") require allocation for the unescaped result.

Each JSON value is represented by a Value struct containing just two machine words: a pointer and a packed integer. The integer uses its high bits to store the value's type (null, boolean, number, string, array, or object) and its low bits for length information. This bit-packing means the overhead per value is minimal—16 bytes on 64-bit systems regardless of the value type.

Arrays and objects are stored as contiguous slices, so iteration is cache-friendly. Object fields are sorted by key during parsing, enabling binary search for lookups.

Trade-offs

This design optimizes for read-heavy workloads where you parse once and query multiple times. If you only need to extract a single value from a large document, a streaming parser or path-based query might be more appropriate.

The parser assumes the input remains valid for the lifetime of the parsed values. If you're parsing from a buffer that gets reused, you'll need to copy strings out before the buffer changes.

Numeric values are stored as their original string representation and parsed on demand when you call Int(), Float(), etc. This avoids precision loss for large integers and defers parsing cost until needed, but means repeated numeric access will re-parse each time.

Documentation

Overview

Package jsonlite provides a lightweight JSON parser optimized for performance through careful memory management. It parses JSON into a tree of Value nodes that can be inspected and serialized back to JSON.

The parser handles all standard JSON types: null, booleans, numbers, strings, arrays, and objects. It properly handles UTF-16 surrogate pairs for emoji and extended Unicode characters.

Index

Constants

View Source
const (
	// DefaultMaxDepth is the default maximum depth for parsing JSON objects.
	DefaultMaxDepth = 100
)

Variables

This section is empty.

Functions

func AppendArray added in v1.2.0

func AppendArray[T any](b []byte, seq iter.Seq[T], fn AppendFunc[T]) []byte

AppendArray appends a JSON array to b by iterating over seq and using fn to serialize each element.

func AppendBool added in v1.2.0

func AppendBool(b []byte, v bool) []byte

AppendBool appends a boolean as JSON to b.

func AppendBytes added in v1.3.0

func AppendBytes(b []byte, data []byte) []byte

AppendBytes appends a byte slice as a base64-encoded JSON string to b.

func AppendFloat added in v1.2.0

func AppendFloat(b []byte, f float64) []byte

AppendFloat appends a floating point number as JSON to b.

func AppendIndentArray added in v1.4.0

func AppendIndentArray[T any](b []byte, seq iter.Seq[T], fn AppendFunc[T], level int, indent IndentFunc) []byte

AppendIndentArray appends a pretty-printed JSON array to b by iterating over seq and using fn to serialize each element. The level parameter specifies the current nesting depth, and indent provides the indentation string for each level.

func AppendIndentObject added in v1.4.0

func AppendIndentObject[T any](b []byte, seq iter.Seq2[string, T], fn AppendFunc[T], level int, indent IndentFunc) []byte

AppendIndentObject appends a pretty-printed JSON object to b by iterating over seq and using fn to serialize each value. Keys are automatically quoted. The level parameter specifies the current nesting depth, and indent provides the indentation string for each level.

func AppendInt added in v1.2.0

func AppendInt(b []byte, n int64) []byte

AppendInt appends an integer as JSON to b.

func AppendNull added in v1.2.0

func AppendNull(b []byte) []byte

AppendNull appends a JSON null to b.

func AppendObject added in v1.2.0

func AppendObject[T any](b []byte, seq iter.Seq2[string, T], fn AppendFunc[T]) []byte

AppendObject appends a JSON object to b by iterating over seq and using fn to serialize each value. Keys are automatically quoted.

func AppendQuote added in v0.5.0

func AppendQuote(b []byte, s string) []byte

AppendQuote appends a JSON quoted string to b and returns the result.

func AppendTime added in v1.3.0

func AppendTime(b []byte, t time.Time) []byte

AppendTime appends a time.Time as a JSON quoted RFC3339Nano string to b.

func AppendUint added in v1.2.0

func AppendUint(b []byte, n uint64) []byte

AppendUint appends an unsigned integer as JSON to b.

func AppendUnquote

func AppendUnquote(b []byte, s string) ([]byte, error)

AppendUnquote appends the unquoted string to the buffer. Returns an error if the string is not properly quoted or contains invalid escapes.

func As added in v0.15.0

func As[T Convertible](v *Value) T

As converts a JSON value to the specified Go type.

For primitive types (bool, int64, uint64, float64, string, time.Duration, time.Time):

  • Follows the same conversion rules as the corresponding As* function
  • Returns zero value for nil or incompatible types

For json.Number:

  • Returns the number as a json.Number string
  • Returns empty string for non-number values

For slice types ([]T):

  • Converts JSON arrays where each element is converted using the primitive T logic
  • Returns nil for non-array values
  • Returns empty slice for empty arrays

For map types (map[string]T):

  • Converts JSON objects where each value is converted using the primitive T logic
  • Returns nil for non-object values
  • Returns empty map for empty objects

For any types:

  • any: Returns the most natural Go representation (bool, int64, uint64, float64, string, []any, map[string]any)
  • []any: Recursively converts array elements to any
  • map[string]any: Recursively converts object values to any

Examples:

val, _ := Parse(`[1, 2, 3]`)
nums := As[[]int64](val)  // []int64{1, 2, 3}

val, _ := Parse(`{"a": 1, "b": 2}`)
m := As[map[string]int64](val)  // map[string]int64{"a": 1, "b": 2}

func Indent added in v1.4.0

func Indent(n int) string

Indent returns a string of spaces for the given nesting level (2 spaces per level). It is optimized to avoid heap allocations for common indentation depths.

func Quote added in v0.5.0

func Quote(s string) string

Quote returns s as a JSON quoted string.

func Unquote

func Unquote(s string) (string, error)

Unquote removes quotes from a JSON string and processes escape sequences. Returns an error if the string is not properly quoted or contains invalid escapes. When the string contains no escape sequences, returns a zero-copy substring.

func Valid added in v0.7.0

func Valid(json string) bool

Valid reports whether json is a valid JSON string. This is similar to encoding/json.Valid but uses the jsonlite tokenizer for efficient zero-allocation validation.

Types

type AppendFunc added in v1.2.0

type AppendFunc[T any] func([]byte, T) []byte

AppendFunc is a function that appends a value of type T to a byte slice.

type Convertible added in v0.15.0

type Convertible interface {
	any |
		bool |
		int64 |
		uint64 |
		float64 |
		json.Number |
		string |
		time.Duration |
		time.Time |
		[]any |
		[]bool |
		[]int64 |
		[]uint64 |
		[]float64 |
		[]json.Number |
		[]string |
		[]time.Duration |
		[]time.Time |
		map[string]any |
		map[string]bool |
		map[string]int64 |
		map[string]uint64 |
		map[string]float64 |
		map[string]json.Number |
		map[string]string |
		map[string]time.Duration |
		map[string]time.Time
}

Convertible is the type constraint for the As function, defining all supported conversion types.

type IndentFunc added in v1.4.0

type IndentFunc func(int) string

IndentFunc returns the indentation string for a given nesting level.

type Iterator added in v0.3.0

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

Iterator provides a streaming interface for traversing JSON values. It automatically handles control tokens (braces, brackets, colons, commas) and presents only the logical JSON values to the caller.

func Iterate added in v0.3.0

func Iterate(json string) *Iterator

Iterate creates a new Iterator for the given JSON string.

func (*Iterator) Array added in v0.4.0

func (it *Iterator) Array(yield func(int, error) bool)

Array iterates over the elements of the current array. The iterator yields the index for each element, and the Iterator is positioned on the element's value. Call Kind(), Value(), Object(), or Array() to process the value. If the value is not consumed before the next iteration, it will be automatically skipped. For null values, no iterations occur.

Must only be called when Kind() == Array or Kind() == Null.

func (*Iterator) Bool added in v0.10.0

func (it *Iterator) Bool() (bool, error)

Bool returns the current value as a boolean. Returns false for null values. Returns an error if the value is not a boolean, null, or a string that can be parsed as a boolean.

func (*Iterator) Depth added in v0.3.0

func (it *Iterator) Depth() int

Depth returns the current nesting depth (0 at top level).

func (*Iterator) Duration added in v0.10.0

func (it *Iterator) Duration() (time.Duration, error)

Duration returns the current value as a time.Duration. Returns 0 for null values. For numbers, the value is interpreted as seconds. For strings, the value is parsed using time.ParseDuration. Returns an error if the value cannot be converted to a duration.

func (*Iterator) Err added in v0.3.0

func (it *Iterator) Err() error

Err returns any error that occurred during iteration.

func (*Iterator) Float added in v0.10.0

func (it *Iterator) Float() (float64, error)

Float returns the current value as a 64-bit floating point number. Returns 0 for null values. Returns an error if the value is not a number, null, or a string that can be parsed as a float.

func (*Iterator) Int added in v0.10.0

func (it *Iterator) Int() (int64, error)

Int returns the current value as a signed 64-bit integer. Floating point numbers are truncated to their integer part. Returns 0 for null values. Returns an error if the value is not a number, null, or a string that can be parsed as an integer.

func (*Iterator) Key added in v0.3.0

func (it *Iterator) Key() string

Key returns the object key for the current value, if inside an object. Returns an empty string if not inside an object or at the top level.

func (*Iterator) Kind added in v0.3.0

func (it *Iterator) Kind() Kind

Kind returns the kind of the current value.

func (*Iterator) Next added in v0.3.0

func (it *Iterator) Next() bool

Next advances the iterator to the next JSON value. Returns true if there is a value to process, false when done or on error.

func (*Iterator) Null added in v0.11.0

func (it *Iterator) Null() bool

Null returns true if the current value is null.

func (*Iterator) Object added in v0.4.0

func (it *Iterator) Object(yield func(string, error) bool)

Object iterates over the key-value pairs of the current object. The iterator yields the key for each field, and the Iterator is positioned on the field's value. Call Kind(), Value(), Object(), or Array() to process the value. If the value is not consumed before the next iteration, it will be automatically skipped. For null values, no iterations occur.

Must only be called when Kind() == Object or Kind() == Null.

func (*Iterator) Reset added in v0.9.0

func (it *Iterator) Reset(json string)

Reset resets the iterator to parse a new JSON string.

func (*Iterator) String added in v0.10.0

func (it *Iterator) String() (string, error)

String returns the current value as a string. Returns "" for null values. Returns an error if the value is not a string or null.

func (*Iterator) Time added in v0.10.0

func (it *Iterator) Time() (time.Time, error)

Time returns the current value as a time.Time. Returns the zero time for null values. For numbers, the value is interpreted as seconds since Unix epoch. For strings, the value is parsed using RFC3339 format. Returns an error if the value cannot be converted to a time.

func (*Iterator) Value added in v0.3.0

func (it *Iterator) Value() (*Value, error)

Value parses and returns the current value. For arrays and objects, this consumes all nested tokens and returns the complete parsed structure.

type Kind

type Kind int

Kind represents the type of a JSON value.

const (
	// Null represents a JSON null value.
	Null Kind = iota
	// True represents a JSON true boolean value.
	True
	// False represents a JSON false boolean value.
	False
	// Number represents a JSON number value.
	Number
	// String represents a JSON string value.
	String
	// Object represents a JSON object value.
	Object
	// Array represents a JSON array value.
	Array
)

type NumberType

type NumberType int

NumberType represents the classification of a JSON number.

const (
	// Int indicates a signed integer number (has a leading minus sign, no decimal point or exponent).
	Int NumberType = iota
	// Uint indicates an unsigned integer number (no minus sign, no decimal point or exponent).
	Uint
	// Float indicates a floating point number (has decimal point or exponent).
	Float
)

func NumberTypeOf

func NumberTypeOf(s string) NumberType

NumberTypeOf returns the classification of a number string.

type Tokenizer added in v0.2.0

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

Tokenizer is a JSON tokenizer that splits input into tokens. It skips whitespace and returns individual JSON tokens one at a time.

func Tokenize added in v0.2.0

func Tokenize(json string) *Tokenizer

Tokenize creates a new Tokenizer for the given JSON string.

func (*Tokenizer) Next added in v0.2.0

func (t *Tokenizer) Next() (token string, ok bool)

Next returns the next token from the input. Returns an empty string and false when there are no more tokens.

type Value

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

Value represents a JSON value of any type.

Value instances as immutable, they can be safely accessed from multiple goroutines.

The zero-value of Value is invalid, all Value instances must be acquired form Parse or from an Iterator.

func Parse

func Parse(data string) (*Value, error)

Parse parses JSON data and returns a pointer to the root Value. Returns an error if the JSON is malformed or empty.

func ParseMaxDepth added in v0.13.0

func ParseMaxDepth(data string, maxDepth int) (*Value, error)

ParseMaxDepth parses JSON data with a maximum nesting depth for objects. Objects at maxDepth <= 0 are stored unparsed and will be lazily parsed when accessed via Lookup(), Array(), or Object() methods. Depth is only decremented for objects, not arrays. Returns an error if the JSON is malformed or empty.

func (*Value) Append

func (v *Value) Append(buf []byte) []byte

Append serializes the Value to JSON and appends it to the buffer. Returns the extended buffer.

func (*Value) Array

func (v *Value) Array(yield func(*Value) bool)

Array iterates over the array elements. Panics if the value is not an array.

func (*Value) Compact added in v0.12.0

func (v *Value) Compact(buf []byte) []byte

Compact appends a compacted JSON representation of the value to buf by recursively reconstructing it from the parsed structure. Unlike Append, this method does not use cached JSON and always regenerates the output.

func (*Value) Float

func (v *Value) Float() float64

Float returns the value as a 64-bit floating point number. Panics if the value is not a number or if parsing fails.

func (*Value) Index added in v0.14.0

func (v *Value) Index(i int) *Value

Index returns the value at index i in an array. Panics if the value is not an array or if the index is out of range.

func (*Value) Int

func (v *Value) Int() int64

Int returns the value as a signed 64-bit integer. Floating point numbers are truncated to their integer part. Panics if the value is not a number or if parsing fails.

func (*Value) JSON added in v0.12.0

func (v *Value) JSON() string

JSON returns the JSON representation of the value.

func (*Value) Kind

func (v *Value) Kind() Kind

Kind returns the type of the JSON value.

func (*Value) Len

func (v *Value) Len() int

Len returns the length of the value. For strings, it returns the number of bytes. For arrays, it returns the number of elements. For objects, it returns the number of fields. Panics if called on other types.

func (*Value) Lookup

func (v *Value) Lookup(k string) *Value

Lookup searches for a field by key in an object and returns a pointer to its value. Returns nil if the key is not found. Panics if the value is not an object.

func (*Value) LookupPath added in v0.14.0

func (v *Value) LookupPath(path ...string) *Value

LookupPath searches for a nested field by following a path of keys. Returns nil if any key in the path is not found. Panics if any intermediate value is not an object. If path is empty, returns the value itself.

func (*Value) Number

func (v *Value) Number() json.Number

Number returns the value as a json.Number. Panics if the value is not a number.

func (*Value) NumberType

func (v *Value) NumberType() NumberType

NumberType returns the classification of the number (int, uint, or float). Panics if the value is not a number.

func (*Value) Object

func (v *Value) Object(yield func(string, *Value) bool)

Object iterates over the object's key/value pairs. Panics if the value is not an object.

func (*Value) Size added in v1.1.0

func (v *Value) Size() int64

Size returns the number of bytes held in memory by the Value, including the Value struct itself, any slice allocations for arrays/objects, and the JSON bytes.

For unparsed (lazy) arrays/objects, this returns only the current memory usage (struct + JSON), not what it would be after parsing.

func (*Value) String

func (v *Value) String() string

String returns the value as a string. For string and number values, returns the raw value. For other types, returns the JSON representation.

func (*Value) Uint

func (v *Value) Uint() uint64

Uint returns the value as an unsigned 64-bit integer. Floating point numbers are truncated to their integer part. Panics if the value is not a number or if parsing fails.

Jump to

Keyboard shortcuts

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