Documentation
¶
Overview ¶
Package jsonbind provides generated, reflection-free JSON document codecs.
Index ¶
- Constants
- Variables
- func AppendAny(dst []byte, v any) []byte
- func AppendBool(dst []byte, v bool) []byte
- func AppendFloat(dst []byte, v float64) []byte
- func AppendFuncFor[T any]() (func([]byte, T) []byte, bool)
- func AppendInt(dst []byte, v int64) []byte
- func AppendRaw(dst []byte, raw []byte) []byte
- func AppendString(dst []byte, s string) []byte
- func AppendUint(dst []byte, v uint64) []byte
- func DecodeJSON[T any](r io.Reader) (T, error)
- func DecodeJSONAny(raw []byte) (any, error)
- func DecodeJSONBool(raw []byte) (bool, error)
- func DecodeJSONBoolSlice(raw []byte) ([]bool, error)
- func DecodeJSONBytes[T any](data []byte) (T, error)
- func DecodeJSONFloat64(raw []byte) (float64, error)
- func DecodeJSONFloat64Slice(raw []byte) ([]float64, error)
- func DecodeJSONInt(raw []byte) (int, error)
- func DecodeJSONInt64(raw []byte) (int64, error)
- func DecodeJSONInt64Slice(raw []byte) ([]int64, error)
- func DecodeJSONIntSlice(raw []byte) ([]int, error)
- func DecodeJSONLimit[T any](r io.Reader, limit int64) (T, error)
- func DecodeJSONMapStringBool(raw []byte) (map[string]bool, error)
- func DecodeJSONMapStringFloat64(raw []byte) (map[string]float64, error)
- func DecodeJSONMapStringInt(raw []byte) (map[string]int, error)
- func DecodeJSONMapStringInt64(raw []byte) (map[string]int64, error)
- func DecodeJSONMapStringString(raw []byte) (map[string]string, error)
- func DecodeJSONString(raw []byte) (string, error)
- func DecodeJSONStringSlice(raw []byte) ([]string, error)
- func EncodeJSON[T any](w io.Writer, v T) error
- func FieldError(field, message string, cause error) error
- func GetBuffer() *[]byte
- func IsBlank(data []byte) bool
- func MaxJSONBodyBytes() int64
- func ParseMap[T any](p *Parser, field, message string, read func(*Parser) (T, error)) (map[string]T, error)
- func ParseSlice[T any](p *Parser, field, message string, read func(*Parser) (T, error)) ([]T, error)
- func PutBuffer(b *[]byte)
- func RawJSONArray(raw []byte) ([][]byte, error)
- func ReadLimitHint(r io.Reader, limit, hint int64) ([]byte, error)
- func RegisterAppend[T any](fn func([]byte, T) []byte)
- func RegisterDecode[T any](fn func([]byte) (T, error))
- func RegisterEncode[T any](fn func(io.Writer, T) error)
- func SetMaxJSONBodyBytes(n int64)
- func SortedKeys[V any](m map[string]V) []string
- type Appender
- type Declaration
- type Decoder
- type Error
- type Parser
- func (p *Parser) Any() (any, error)
- func (p *Parser) ArrayNext(n int) (bool, error)
- func (p *Parser) ArrayStart() (isNull bool, err error)
- func (p *Parser) Bool() (bool, error)
- func (p *Parser) End() error
- func (p *Parser) Float64() (float64, error)
- func (p *Parser) Int() (int, error)
- func (p *Parser) Int64() (int64, error)
- func (p *Parser) IsNull() bool
- func (p *Parser) ObjectKey(n int) (key []byte, ok bool, err error)
- func (p *Parser) ObjectStart() (isNull bool, err error)
- func (p *Parser) RawValue() ([]byte, error)
- func (p *Parser) Reset(data []byte)
- func (p *Parser) SkipValue() error
- func (p *Parser) String() (string, error)
Constants ¶
const DefaultMaxJSONBodyBytes int64 = 1 << 20
DefaultMaxJSONBodyBytes is the default JSON document limit (1 MiB).
Variables ¶
var ErrBodyTooLarge = errors.New("jsonbind: JSON body too large")
ErrBodyTooLarge reports that a JSON document exceeded its configured limit.
Functions ¶
func AppendAny ¶ added in v0.4.0
AppendAny appends an arbitrary Go value produced by rest-field decoding. It covers the shapes Parser.Any yields plus the common scalar types, and any type carrying its own encoder through Appender; anything else is written as null rather than failing an otherwise valid response.
The Appender arm is what keeps a user type out of that null. Before it a value the switch did not name — which is every named struct — reached the default and encoded as null, producing a wrong document rather than a reported error. It sits after the concrete cases so a builtin shape is still matched by identity rather than by method set.
func AppendBool ¶ added in v0.4.0
AppendBool appends a JSON boolean.
func AppendFloat ¶ added in v0.4.0
AppendFloat appends a JSON number using encoding/json's formatting: shortest round-trip, switching to exponent form outside [1e-6, 1e21) and trimming the exponent's leading zero.
func AppendFuncFor ¶ added in v0.5.21
AppendFuncFor returns T's registered append-form encoder. Callers that encode the same T repeatedly — a stream writing events — resolve it once instead of paying a registry lookup per value.
func AppendRaw ¶ added in v0.4.0
AppendRaw appends an already-encoded JSON value, or null when it is empty.
func AppendString ¶ added in v0.4.0
AppendString appends a JSON string literal. Like encoding/json's encoder it escapes <, > and & so the result is safe to embed in HTML, and U+2028/U+2029 so it stays valid JavaScript.
func AppendUint ¶ added in v0.4.0
AppendUint appends a JSON number.
func DecodeJSON ¶
DecodeJSON decodes one JSON value from r into T using a generated codec. It does not inspect HTTP headers or use reflection on T's fields.
func DecodeJSONAny ¶ added in v0.4.0
DecodeJSONAny decodes any JSON value into the Go shapes encoding/json uses for an `any` destination.
func DecodeJSONBool ¶
DecodeJSONBool decodes a JSON boolean.
func DecodeJSONBoolSlice ¶
DecodeJSONBoolSlice decodes a JSON array of booleans.
func DecodeJSONBytes ¶ added in v0.5.4
DecodeJSONBytes decodes one JSON value already held in memory into T.
The reader entries above exist because an HTTP body arrives as a stream. A caller that already has the whole document — a WebSocket message, say — has nothing to read, and going through a reader would allocate one and copy the document into a second buffer for every call.
The limit belongs to whoever produced the bytes, so none is applied here. A type carrying Decoder is read through it, on the terms EncodeJSON states for the other direction.
func DecodeJSONFloat64 ¶
DecodeJSONFloat64 decodes a JSON number as float64.
func DecodeJSONFloat64Slice ¶
DecodeJSONFloat64Slice decodes a JSON array of floats.
func DecodeJSONInt ¶
DecodeJSONInt decodes a JSON number as int.
func DecodeJSONInt64 ¶
DecodeJSONInt64 decodes a JSON number as int64.
func DecodeJSONInt64Slice ¶
DecodeJSONInt64Slice decodes a JSON array of int64s.
func DecodeJSONIntSlice ¶
DecodeJSONIntSlice decodes a JSON array of ints.
func DecodeJSONLimit ¶
DecodeJSONLimit is DecodeJSON with a per-call byte limit. A non-positive limit uses MaxJSONBodyBytes.
func DecodeJSONMapStringBool ¶ added in v0.4.0
DecodeJSONMapStringBool decodes a JSON object of booleans.
func DecodeJSONMapStringFloat64 ¶ added in v0.4.0
DecodeJSONMapStringFloat64 decodes a JSON object of floats.
func DecodeJSONMapStringInt ¶ added in v0.4.0
DecodeJSONMapStringInt decodes a JSON object of ints.
func DecodeJSONMapStringInt64 ¶ added in v0.4.0
DecodeJSONMapStringInt64 decodes a JSON object of int64s.
func DecodeJSONMapStringString ¶
DecodeJSONMapStringString decodes a JSON object of strings.
func DecodeJSONString ¶
DecodeJSONString decodes a JSON string value.
func DecodeJSONStringSlice ¶
DecodeJSONStringSlice decodes a JSON array of strings.
func EncodeJSON ¶
EncodeJSON encodes v as compact JSON to w using a generated codec, or, for a type carrying its own, through Appender.
The interface is tried first. A type this run planned and also carries a method is one whose author wrote an encoder, and encoding it through the generated one instead would silently produce bytes they did not intend. This is how encoding/json resolves the same conflict, letting the method win over walking the fields. For a declared codec the two are the same code, since the emitted method delegates to the emitted function.
It does not set HTTP headers or status.
func FieldError ¶
FieldError annotates a JSON decoding error with its document field.
func GetBuffer ¶ added in v0.4.0
func GetBuffer() *[]byte
GetBuffer borrows an encode buffer. Generated code returns it with PutBuffer once the bytes have been written out.
func IsBlank ¶ added in v0.4.0
IsBlank reports whether data holds no JSON document at all. Generated decoders treat that as the zero value rather than a parse error, which is how an absent body and an empty config file have always behaved.
func MaxJSONBodyBytes ¶
func MaxJSONBodyBytes() int64
MaxJSONBodyBytes returns the effective JSON document limit.
func ParseMap ¶ added in v0.4.3
func ParseMap[T any](p *Parser, field, message string, read func(*Parser) (T, error)) (map[string]T, error)
ParseMap decodes a JSON object field, reading each member value with read. A JSON null decodes as a nil map and an empty object as a non-nil empty one. Errors are annotated the same way as ParseSlice.
func ParseSlice ¶ added in v0.4.3
func ParseSlice[T any](p *Parser, field, message string, read func(*Parser) (T, error)) ([]T, error)
ParseSlice decodes a JSON array field, reading each element with read. A JSON null decodes as a nil slice and an empty array as a non-nil empty one. Structural errors are annotated with the field's document name; an element error is annotated with message, or passed through unchanged when message is empty so a nested decoder can report its own fields.
func PutBuffer ¶ added in v0.4.0
func PutBuffer(b *[]byte)
PutBuffer returns an encode buffer to the pool. Oversized buffers are dropped so one large document does not pin memory for the process lifetime.
func RawJSONArray ¶
RawJSONArray splits a JSON array into its raw elements. Elements alias raw.
func ReadLimitHint ¶ added in v0.4.0
ReadLimitHint reads at most limit bytes from r, with an expected size. A caller that knows the length up front — an HTTP handler with a Content-Length, say — lets the whole body land in one allocation instead of the repeated grow-and-copy io.ReadAll performs. A wrong hint costs nothing but the usual growth.
func RegisterAppend ¶ added in v0.5.21
RegisterAppend registers a generated append-form encoder for T: the function a generated writer body is built from, appending one compact JSON value with no trailing newline.
The writer form above frames and writes a whole document, which is right for a response body but wrong for a caller composing a larger frame — an SSE event, a JSON array element — who would pay a second buffer and copy to unwrap it. This form hands the bytes over where they are wanted instead.
func RegisterDecode ¶
RegisterDecode registers a generated JSON document decoder for T.
func RegisterEncode ¶
RegisterEncode registers a generated compact JSON encoder for T.
func SetMaxJSONBodyBytes ¶
func SetMaxJSONBodyBytes(n int64)
SetMaxJSONBodyBytes changes the process-wide JSON document limit.
func SortedKeys ¶ added in v0.4.0
SortedKeys orders map keys so a map encodes deterministically, matching encoding/json's behaviour. Generated encoders call it for every map-typed field and for payload:"*" rest maps.
Types ¶
type Appender ¶ added in v0.5.10
Appender is a type that encodes itself as JSON by appending to dst and returning the extended slice.
This is the method form of what the generator already emits, so a generated codec satisfies it by delegation and a hand-written one costs the same as the generated body would have.
There is no error result. The append path has none anywhere below this point, and every value that reaches it is one the caller already holds, so an implementation that cannot produce a document for its own value has no state worth reporting. An implementation must append valid JSON for every value of its type.
type Declaration ¶ added in v0.5.10
type Declaration struct{}
Declaration is what an annotation below returns. It carries nothing: the value exists only so the annotation can be written as a package-level declaration, which is where generation reads it.
func GenerateCodec ¶ added in v0.5.10
func GenerateCodec[T any]() Declaration
GenerateCodec asks for T's encoder and decoder, and for both methods.
func GenerateDecoder ¶ added in v0.5.10
func GenerateDecoder[T any]() Declaration
GenerateDecoder asks for T's decoder and for Decoder alone. Use it for a type only ever read.
func GenerateEncoder ¶ added in v0.5.10
func GenerateEncoder[T any]() Declaration
GenerateEncoder asks for T's encoder and for Appender alone. Use it for a type only ever written, so a decoder is not carried into the binary with it.
type Decoder ¶ added in v0.5.10
Decoder is a type that decodes one complete JSON document into itself.
data holds exactly one JSON value. The implementation fills the receiver, so the method belongs on the pointer and *T rather than T is what satisfies this.
Unlike Appender, this does not compose to any depth for free: a nested field is decoded by walking a Parser, and a method taking a complete slice joins that walk only by being handed the sub-document, which costs scanning that region twice. Generated decoders take that path for a field whose type satisfies this and no other field, so a document holding none pays nothing.
type Error ¶
type Error struct {
Code string
Message string
Field string
// contains filtered or unexported fields
}
Error describes a transport-neutral JSON mapping failure.
type Parser ¶ added in v0.4.0
type Parser struct {
// contains filtered or unexported fields
}
Parser reads a JSON document in a single forward pass. Generated codecs drive it directly: values are parsed out of the input buffer in place, so decoding allocates only the strings, slices and maps that end up in the result.
It does not use reflect and does not import encoding/json.
func NewParser ¶ added in v0.4.0
NewParser returns a Parser reading data. data is not copied, and values returned by RawValue alias it.
func (*Parser) Any ¶ added in v0.4.0
Any decodes an arbitrary JSON value into the same Go shapes encoding/json produces for an `any` destination.
func (*Parser) ArrayNext ¶ added in v0.4.0
ArrayNext reports whether another element follows. n is the element index.
func (*Parser) ArrayStart ¶ added in v0.4.0
ArrayStart consumes '['. A JSON null reports isNull and consumes the literal.
func (*Parser) End ¶ added in v0.4.0
End reports an error when anything but whitespace follows the document.
func (*Parser) ObjectKey ¶ added in v0.4.0
ObjectKey returns the next member name, or ok=false at '}'. n is the zero-based member index and tells the parser whether a comma is required, so the parser needs no nesting stack of its own.
The returned key aliases parser scratch space and is only valid until the next ObjectKey call.
func (*Parser) ObjectStart ¶ added in v0.4.0
ObjectStart consumes '{'. A JSON null reports isNull and consumes the literal.
func (*Parser) RawValue ¶ added in v0.4.0
RawValue returns the next value's bytes as a subslice of the input. The result aliases the parser's buffer and must be copied to outlive it.