writer

package
v0.0.0-...-4ebe608 Latest Latest
Warning

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

Go to latest
Published: Nov 27, 2025 License: Apache-2.0 Imports: 15 Imported by: 0

README

Default JSON writers

Functionality

A JSON writer implements one or several writer interfaces.

These interfaces build a stream of JSON output into some underlying io.Writer from JSON token, JSON values, Store values or native go values.

This package exposes several such writers:

  • an unbuffered writer
  • a buffered writer
  • an indented writer (to output "pretty JSON") - buffered -
  • a YAML writer, that outputs JSON tokens and values as a YAML document

TODOs:

  • [] YAML output is not great, because at this moment, strings remain JSON strings, without accounting for YAML escaping rules.

Performance

  • Allocations

The exposed writers generally amortize all internal allocations. So most standard benchmarks would show up zero allocation.

There is an exception: when writing numerical values using the Number() method with types from the math/big standard library, serialization occurs using their AppendText method.

Since math/big is not optimized for zero-allocation, there are a few buffered allocated internally by this library.

TODOs:

  • [] there are still some learnings to be learnt from easyjson/jwriter

Background and credits

This JSON writer has been largely inspired by the work from https://github.com/mailru/easyjson.

We've kept the concept of a writer to proces JSON tokens and escape strings, very much like in https://github.com/mailru/easyjson/blob/master/jwriter/writer.go.

However, this implementation introduces a few significant differences:

  • several implementations of the writers interfaces may be proposed, possibly optimized for different use-cases
  • unlike the easyjson version, we don't want to support complex types such as objects or arrays, only scalar values
  • this implementation supports the types defined to support JSON et JSON tokens by the other modules exposed in github.com/fredbi/core
  • this makes the writer suitable for:
  • the idea of a "chunked buffer" has been revisited and reimplementented. It may or may not be a good option, depending on the use-case. So we propose an unbuffered alternative.
  • this implementation leverages memory pools more systematically

Documentation

Overview

Package writer exposes an implementation of the JSON writer interface writers.Writer.

It knows how to write JSON tokens token.T or token.VT, JSON values values.Value and values.InternedKey, JSON scalar types (types.Boolean, types.String, types.Number, types.NullType) or any go scalar value that fits as JSON.

It handles proper JSON string escaping.

It is NOT intended to write down as JSON complex structures such as objects or arrays, so you won't find options such as "should nil or empty slices or maps be rendered or not".

Similarly, it handles "null" values as actual values. Absent data (i.e. a nil slice of bytes) is not considered a "null" value and is therefore not rendered at all.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RedeemBuffered

func RedeemBuffered(w *Buffered)

func RedeemIndented

func RedeemIndented(w *Indented)

func RedeemUnbuffered

func RedeemUnbuffered(w *Unbuffered)

RedeemUnbuffered relinquishes a borrowed Unbuffered writer back to the global pool.

Inner resources are relinquished by this call.

func RedeemYAML

func RedeemYAML(w *YAML)

Types

type Buffered

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

Buffered JSON writer.

func BorrowBuffered

func BorrowBuffered(writer io.Writer, opts ...BufferedOption) *Buffered

func NewBuffered

func NewBuffered(w io.Writer, opts ...BufferedOption) *Buffered

func (*Buffered) Bool

func (w *Buffered) Bool(v bool)

Bool writes a boolean value as JSON.

func (*Buffered) Colon

func (w *Buffered) Colon()

Colon writes a colon separator, ':'.

func (*Buffered) Comma

func (w *Buffered) Comma()

Comma writes a comma separator, ','.

func (*Buffered) EndArray

func (w *Buffered) EndArray()

EndArray writes an end-of-array separator, i.e. ']'.

func (*Buffered) EndObject

func (w *Buffered) EndObject()

EndObject writes an end-of-object separator, i.e. '}'.

func (*Buffered) Flush

func (w *Buffered) Flush() error

Flush the internal buffer of the Buffered writer to the underlying io.Writer.

func (*Buffered) JSONBoolean

func (w *Buffered) JSONBoolean(value types.Boolean)

JSONBoolean writes a JSON value of types.Boolean.

Nothing is written if the value is undefined.

func (*Buffered) JSONNull

func (w *Buffered) JSONNull(value types.NullType)

JSONNull writes a JSON value of types.NullType, i.e. the "null" token.

Nothing is written if the value is undefined.

func (*Buffered) JSONNumber

func (w *Buffered) JSONNumber(value types.Number)

JSONNumber writes a JSON value of types.Number.

Nothing is written if the value is undefined.

func (*Buffered) JSONString

func (w *Buffered) JSONString(value types.String)

JSONString writes a JSON value of types.String.

Nothing is written if the value is undefined.

func (*Buffered) Key

func (w *Buffered) Key(key values.InternedKey)

Key write a key values.InternedKey followed by a colon (":").

func (*Buffered) Null

func (w *Buffered) Null()

Null writes a null token ("null").

func (*Buffered) Number

func (w *Buffered) Number(v any)

Number writes a number from any native numerical go type, except complex numbers.

Types from the math/big package are supported: big.Int, big.Rat, big.Float.

Numbers provided as a slice of bytes are also supported (no check is carried out).

The method panics if the argument is not a numerical type or []byte.

func (*Buffered) NumberBytes

func (w *Buffered) NumberBytes(data []byte)

NumberBytes writes a slice of bytes as a JSON number.

No check is carried out.

func (*Buffered) NumberCopy

func (w *Buffered) NumberCopy(r io.Reader)

NumberCopy writes the bytes consumed from an io.Reader as a JSON number.

No check is carried out.

func (*Buffered) Raw

func (w *Buffered) Raw(data []byte)

Raw appends raw bytes to the buffer, without quotes and without escaping.

func (*Buffered) RawCopy

func (w *Buffered) RawCopy(r io.Reader)

RawCopy writes the bytes consumed from an io.Reader, without quotes and without escaping.

func (*Buffered) Reset

func (w *Buffered) Reset()

func (*Buffered) StartArray

func (w *Buffered) StartArray()

StartArray writes a start-of-array separator, i.e. '['.

func (*Buffered) StartObject

func (w *Buffered) StartObject()

StartObject writes a start-of-object separator, i.e. '{'.

func (*Buffered) String

func (w *Buffered) String(s string)

String writes a string as a JSON string value enclosed by double quotes, with escaping.

The empty string is a legit input.

func (*Buffered) StringBytes

func (w *Buffered) StringBytes(data []byte)

StringBytes writes a slice of bytes as a JSON string enclosed by double quotes ('"'), with escaping.

An empty slice is a legit input.

func (*Buffered) StringCopy

func (w *Buffered) StringCopy(r io.Reader)

func (*Buffered) StringRunes

func (w *Buffered) StringRunes(data []rune)

StringRunes writes a slice of bytes as a JSON string enclosed by double quotes ('"'), with escaping.

An empty slice is a legit input.

func (*Buffered) Token

func (w *Buffered) Token(tok token.T)

Token writes a token token.T from a lexer.

For key tokens, you'd need to call explicitly with the following colon token.

func (*Buffered) Value

func (w *Buffered) Value(v values.Value)

Value writes a values.Value

func (*Buffered) VerbatimToken

func (w *Buffered) VerbatimToken(tok token.VT)

VerbatimToken writes a verbatim token token.VT from a verbatim lexer.

Non-significant white-space preceding each token is written to the buffer.

func (*Buffered) VerbatimValue

func (w *Buffered) VerbatimValue(value values.VerbatimValue)

type BufferedOption

type BufferedOption func(*bufferedOptions)

BufferedOption configures the Buffered writer.

func WithBufferSize

func WithBufferSize(size int) BufferedOption

WithBufferSize specifies the size in bytes of the write buffer.

The default is 4096.

The minimum value is 6 bytes.

type Error

type Error string

Error is a sentinel error type for all errors raised by this package.

const (
	// ErrDefaultWriter is a sentinel error that wraps all errors raised by this package.
	ErrDefaultWriter Error = "error in default writer"

	// ErrUnsupportedInterface means that a method is called but the underlying buffer does not support this interface.
	ErrUnsupportedInterface Error = "the underlying buffer does not support this interface"
)

func (Error) Error

func (e Error) Error() string

type Indented

type Indented struct {
	*Buffered
	// contains filtered or unexported fields
}

func BorrowIndented

func BorrowIndented(writer io.Writer, opts ...IndentedOption) *Indented

func NewIndented

func NewIndented(w io.Writer, opts ...IndentedOption) *Indented

func (*Indented) Bool

func (w *Indented) Bool(v bool)

func (*Indented) Colon

func (w *Indented) Colon()

Colon writes a colon separator, ':'.

func (*Indented) Comma

func (w *Indented) Comma()

Comma writes a comma separator, ','.

func (*Indented) EndArray

func (w *Indented) EndArray()

EndArray writes an end-of-array separator, i.e. ']'.

func (*Indented) EndObject

func (w *Indented) EndObject()

EndObject writes an end-of-object separator, i.e. '}'.

func (*Indented) Flush

func (w *Indented) Flush() error

func (*Indented) JSONBoolean

func (w *Indented) JSONBoolean(value types.Boolean)

func (*Indented) JSONNull

func (w *Indented) JSONNull(value types.NullType)

func (*Indented) JSONNumber

func (w *Indented) JSONNumber(value types.Number)

func (*Indented) JSONString

func (w *Indented) JSONString(value types.String)

func (*Indented) Key

func (w *Indented) Key(key values.InternedKey)

func (*Indented) Null

func (w *Indented) Null()

func (*Indented) Number

func (w *Indented) Number(v any)

func (*Indented) NumberBytes

func (w *Indented) NumberBytes(data []byte)

func (*Indented) NumberCopy

func (w *Indented) NumberCopy(r io.Reader)

func (*Indented) Raw

func (w *Indented) Raw(data []byte)

func (*Indented) RawCopy

func (w *Indented) RawCopy(r io.Reader)

func (*Indented) Reset

func (w *Indented) Reset()

func (*Indented) StartArray

func (w *Indented) StartArray()

StartArray writes a start-of-array separator, i.e. '['.

func (*Indented) StartObject

func (w *Indented) StartObject()

StartObject writes a start-of-object separator, i.e. '{'.

func (*Indented) String

func (w *Indented) String(s string)

func (*Indented) StringBytes

func (w *Indented) StringBytes(data []byte)

func (*Indented) StringCopy

func (w *Indented) StringCopy(r io.Reader)

func (*Indented) StringRunes

func (w *Indented) StringRunes(data []rune)

func (*Indented) Token

func (w *Indented) Token(tok token.T)

func (*Indented) Value

func (w *Indented) Value(v values.Value)

func (Indented) VerbatimToken

func (w Indented) VerbatimToken(tok token.VT)

VerbatimToken writes a verbatim token token.VT from a verbatim lexer.

Non-significant white-space preceding each token is written to the buffer.

func (Indented) VerbatimValue

func (w Indented) VerbatimValue(value values.VerbatimValue)

type IndentedOption

type IndentedOption func(*indentedOptions)

func WithIndent

func WithIndent(indent string) IndentedOption

func WithIndentBufferedOptions

func WithIndentBufferedOptions(opts ...BufferedOption) IndentedOption

type Unbuffered

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

Unbuffered JSON writer. Unbuffered implements writers.StoreWriter, writers.JSONWriter, writers.TokenWriter and writers.VerbatimWriter.

It knows how to render JSON tokens and JSON values to an underlying io.Writer.

All writes are passed straight-through, and no flushing is required.

Strings are escaped with default JSON escaping rule for tabs, new lines, line feeds, backslashes and double quotes.

There is no attempt to do anything special regarding empty or null values:

  • an undefined value (or nil data) is not rendered
  • a null value is necessarily defined explicitly and is rendered with the "null" token

Concurrency

Unbuffered is not intended for concurrent use.

func BorrowUnbuffered

func BorrowUnbuffered(writer io.Writer, opts ...UnbufferedOption) *Unbuffered

BorrowUnbuffered recycles an Unbuffered writer from the global pool.

BorrowUnbuffered is equivalent to NewUnbuffered, but may save the allocation of new resources if they are readily available in the pool.

The caller is responsible for calling RedeemUnbuffered after the work is done, and relinquish resources to the pool.

func NewUnbuffered

func NewUnbuffered(w io.Writer, opts ...UnbufferedOption) *Unbuffered

NewUnbuffered JSON writer that copies JSON to io.Writer w, without buffering.

func (*Unbuffered) Bool

func (w *Unbuffered) Bool(v bool)

Bool writes a boolean value as JSON.

func (*Unbuffered) Colon

func (w *Unbuffered) Colon()

Colon writes a colon separator, ':'.

func (*Unbuffered) Comma

func (w *Unbuffered) Comma()

Comma writes a comma separator, ','.

func (*Unbuffered) EndArray

func (w *Unbuffered) EndArray()

EndArray writes an end-of-array separator, i.e. ']'.

func (*Unbuffered) EndObject

func (w *Unbuffered) EndObject()

EndObject writes an end-of-object separator, i.e. '}'.

func (*Unbuffered) JSONBoolean

func (w *Unbuffered) JSONBoolean(value types.Boolean)

JSONBoolean writes a JSON value of types.Boolean.

Nothing is written if the value is undefined.

func (*Unbuffered) JSONNull

func (w *Unbuffered) JSONNull(value types.NullType)

JSONNull writes a JSON value of types.NullType, i.e. the "null" token.

Nothing is written if the value is undefined.

func (*Unbuffered) JSONNumber

func (w *Unbuffered) JSONNumber(value types.Number)

JSONNumber writes a JSON value of types.Number.

Nothing is written if the value is undefined.

func (*Unbuffered) JSONString

func (w *Unbuffered) JSONString(value types.String)

JSONString writes a JSON value of types.String.

Nothing is written if the value is undefined.

func (*Unbuffered) Key

func (w *Unbuffered) Key(key values.InternedKey)

Key write a key values.InternedKey followed by a colon (":").

func (*Unbuffered) Null

func (w *Unbuffered) Null()

Null writes a null token ("null").

func (*Unbuffered) Number

func (w *Unbuffered) Number(v any)

Number writes a number from any native numerical go type, except complex numbers.

Types from the math/big package are supported: big.Int, big.Rat, big.Float.

Numbers provided as a slice of bytes are also supported (no check is carried out).

The method panics if the argument is not a numerical type or []byte.

func (*Unbuffered) NumberBytes

func (w *Unbuffered) NumberBytes(data []byte)

NumberBytes writes a slice of bytes as a JSON number.

No check is carried out.

func (*Unbuffered) NumberCopy

func (w *Unbuffered) NumberCopy(r io.Reader)

NumberCopy writes the bytes consumed from an io.Reader as a JSON number.

No check is carried out.

func (*Unbuffered) Raw

func (w *Unbuffered) Raw(data []byte)

Raw appends raw bytes to the buffer, without quotes and without escaping.

func (*Unbuffered) RawCopy

func (w *Unbuffered) RawCopy(r io.Reader)

RawCopy writes the bytes consumed from an io.Reader, without quotes and without escaping.

func (*Unbuffered) Reset

func (w *Unbuffered) Reset()

func (*Unbuffered) StartArray

func (w *Unbuffered) StartArray()

StartArray writes a start-of-array separator, i.e. '['.

func (*Unbuffered) StartObject

func (w *Unbuffered) StartObject()

StartObject writes a start-of-object separator, i.e. '{'.

func (*Unbuffered) String

func (w *Unbuffered) String(s string)

String writes a string as a JSON string value enclosed by double quotes, with escaping.

The empty string is a legit input.

func (*Unbuffered) StringBytes

func (w *Unbuffered) StringBytes(data []byte)

StringBytes writes a slice of bytes as a JSON string enclosed by double quotes ('"'), with escaping.

An empty slice is a legit input.

func (*Unbuffered) StringCopy

func (w *Unbuffered) StringCopy(r io.Reader)

func (*Unbuffered) StringRunes

func (w *Unbuffered) StringRunes(data []rune)

StringRunes writes a slice of bytes as a JSON string enclosed by double quotes ('"'), with escaping.

An empty slice is a legit input.

func (*Unbuffered) Token

func (w *Unbuffered) Token(tok token.T)

Token writes a token token.T from a lexer.

For key tokens, you'd need to call explicitly with the following colon token.

func (*Unbuffered) Value

func (w *Unbuffered) Value(v values.Value)

Value writes a values.Value

func (*Unbuffered) VerbatimToken

func (w *Unbuffered) VerbatimToken(tok token.VT)

VerbatimToken writes a verbatim token token.VT from a verbatim lexer.

Non-significant white-space preceding each token is written to the buffer.

func (*Unbuffered) VerbatimValue

func (w *Unbuffered) VerbatimValue(value values.VerbatimValue)

type UnbufferedOption

type UnbufferedOption func(*unbufferedOptions)

UnbufferedOption configures the Unbuffered writer.

type YAML

type YAML struct {
	*Buffered
	// contains filtered or unexported fields
}

TODO: optionally add yaml doc separator "---" TODO: text escaping rules

func BorrowYAML

func BorrowYAML(writer io.Writer, opts ...YAMLOption) *YAML

func NewYAML

func NewYAML(w io.Writer, opts ...YAMLOption) *YAML

func (*YAML) Bool

func (w *YAML) Bool(v bool)

func (*YAML) Colon

func (w *YAML) Colon()

Colon writes a colon separator, ':'.

func (*YAML) Comma

func (w *YAML) Comma()

Comma writes a comma separator, ','.

func (*YAML) EndArray

func (w *YAML) EndArray()

EndArray writes an end-of-array separator, i.e. ']'.

func (*YAML) EndObject

func (w *YAML) EndObject()

EndObject writes an end-of-object separator, i.e. '}'.

func (*YAML) Flush

func (w *YAML) Flush() error

func (*YAML) IndentLevel

func (w *YAML) IndentLevel() int

IndentLevel yields the current depth of the container stack.

Example: the following JSON fragment returns 4 tokens, with the IndentLevel evolving like so:

Input: [ { "a": 1 } ]
Level: 1 2   22 2 1 0

func (*YAML) JSONBoolean

func (w *YAML) JSONBoolean(value types.Boolean)

func (*YAML) JSONNull

func (w *YAML) JSONNull(_ types.NullType)

func (*YAML) JSONNumber

func (w *YAML) JSONNumber(value types.Number)

func (*YAML) JSONString

func (w *YAML) JSONString(value types.String)

func (*YAML) Key

func (w *YAML) Key(key values.InternedKey)

func (*YAML) Null

func (w *YAML) Null()

func (*YAML) Number

func (w *YAML) Number(v any)

func (*YAML) NumberBytes

func (w *YAML) NumberBytes(data []byte)

func (*YAML) NumberCopy

func (w *YAML) NumberCopy(r io.Reader)

func (*YAML) Raw

func (w *YAML) Raw(data []byte)

func (*YAML) RawCopy

func (w *YAML) RawCopy(r io.Reader)

func (*YAML) Reset

func (w *YAML) Reset()

func (*YAML) StartArray

func (w *YAML) StartArray()

StartArray writes a start-of-array separator, i.e. '['.

func (*YAML) StartObject

func (w *YAML) StartObject()

StartObject writes a start-of-object separator, i.e. '{'.

func (*YAML) String

func (w *YAML) String(s string)

func (*YAML) StringBytes

func (w *YAML) StringBytes(data []byte)

func (*YAML) StringCopy

func (w *YAML) StringCopy(r io.Reader)

func (*YAML) StringRunes

func (w *YAML) StringRunes(data []rune)

func (*YAML) Token

func (w *YAML) Token(tok token.T)

func (*YAML) Value

func (w *YAML) Value(v values.Value)

func (YAML) VerbatimToken

func (w YAML) VerbatimToken(tok token.VT)

VerbatimToken writes a verbatim token token.VT from a verbatim lexer.

Non-significant white-space preceding each token is written to the buffer.

func (YAML) VerbatimValue

func (w YAML) VerbatimValue(value values.VerbatimValue)

type YAMLOption

type YAMLOption func(*yamlOptions)

func WithYAMLBufferedOptions

func WithYAMLBufferedOptions(opts ...BufferedOption) YAMLOption

func WithYAMLDocHeading

func WithYAMLDocHeading(enabled bool) YAMLOption

func WithYAMLIndent

func WithYAMLIndent(indent string) YAMLOption

Jump to

Keyboard shortcuts

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