Package json

import "encoding/json/v2"
Overview
Index
Examples

Overview ▾

Package json implements semantic processing of JSON as specified in RFC 8259. JSON is a simple data interchange format that can represent primitive data types such as booleans, strings, and numbers, in addition to structured data types such as objects and arrays.

See the Working with JSON tutorial for an introduction to this package.

Marshal and Unmarshal encode and decode Go values to/from JSON text contained within a []byte. MarshalWrite and UnmarshalRead operate on JSON text by writing to or reading from an io.Writer or io.Reader. MarshalEncode and UnmarshalDecode operate on JSON text by encoding to or decoding from a jsontext.Encoder or jsontext.Decoder. Options may be passed to each of the marshal or unmarshal functions to configure the semantic behavior of marshaling and unmarshaling (i.e., alter how JSON data is understood as Go data and vice versa). jsontext.Options may also be passed to the marshal or unmarshal functions to configure the syntactic behavior of encoding or decoding.

The data types of JSON are mapped to/from the data types of Go based on the closest logical equivalent between the two type systems. For example, a JSON boolean corresponds with a Go bool, a JSON string corresponds with a Go string, a JSON number corresponds with a Go int, uint or float, a JSON array corresponds with a Go slice or array, and a JSON object corresponds with a Go struct or map. See the documentation on Marshal and Unmarshal for a comprehensive list of how the JSON and Go type systems correspond.

Arbitrary Go types can customize their JSON representation by implementing Marshaler, MarshalerTo, Unmarshaler, or UnmarshalerFrom. This provides authors of Go types with control over how their types are serialized as JSON. Alternatively, users can implement functions that match MarshalFunc, MarshalToFunc, UnmarshalFunc, or UnmarshalFromFunc to specify the JSON representation for arbitrary types. This provides callers of JSON functionality with control over how any arbitrary type is serialized as JSON.

JSON Representation of Go structs

A Go struct is naturally represented as a JSON object, where each Go struct field corresponds with a JSON object member. When marshaling, all Go struct fields are recursively encoded in depth-first order as JSON object members except those that are ignored or omitted. When unmarshaling, JSON object members are recursively decoded into the corresponding Go struct fields. Object members that do not match any struct fields, also known as “unknown members”, are ignored by default or rejected if RejectUnknownMembers is specified.

The representation of each struct field can be customized in the "json" struct field tag, where the tag is a comma-separated list of options. As a special case, if the entire tag is `json:"-"`, then the field is ignored with regard to its JSON representation. Some options also have equivalent behavior controlled by a caller-specified Options. Field-specified options take precedence over caller-specified options.

The first option is the JSON object name override for the Go struct field. If the name is not specified, then the Go struct field name is used as the JSON object name. By default, unmarshaling uses case-sensitive matching to identify the Go struct field associated with a JSON object name.

After the name, the following tag options are supported:

  • omitzero: When marshaling, the "omitzero" option specifies that the struct field should be omitted if the field value is zero as determined by the "IsZero() bool" method if present, otherwise based on whether the field is the zero Go value. This option has no effect when unmarshaling.

  • omitempty: When marshaling, the "omitempty" option specifies that the struct field should be omitted if the field value would have been encoded as a JSON null, empty string, empty object, or empty array. This option has no effect when unmarshaling.

  • string: The "string" option specifies that StringifyNumbers be set when marshaling or unmarshaling a struct field value. This causes types that would normally be encoded as a JSON number to instead be encoded as a JSON number quoted within a JSON string, and to be decoded from a JSON string containing the JSON number without any surrounding whitespace. The "string" option only applies to the top-level of the Go struct field value. It is an error to apply this option to any type that does not encode as a JSON number. Note that composite types such as arrays, slices, structs, and maps do not encode as a JSON number, so applying this option will cause an error rather than affecting JSON numbers within such types. This extra level of encoding is often necessary since many JSON parsers cannot precisely represent 64-bit integers.

  • case: When unmarshaling, the "case" option specifies how JSON object names are matched with the JSON name for Go struct fields. The option is a key-value pair specified as "case:value" where the value must either be 'ignore' or 'strict'. The 'ignore' value specifies that matching is case-insensitive, and also ignores dashes and underscores. If multiple fields match, then the field with an exact name match is selected, otherwise an error is reported because the choice of field to unmarshal into is ambiguous. The 'strict' value specifies that matching is case-sensitive. This takes precedence over the MatchCaseInsensitiveNames option.

  • embed: The "embed" option specifies that the JSON representable content of this field type is to be promoted as if it were specified in the parent struct. It is the JSON equivalent of Go struct embedding. A Go embedded field is implicitly JSON embedded unless an explicit JSON name is specified. The embedded field must be a Go struct (that does not implement any JSON methods), jsontext.Value, map[~string]T, or an unnamed pointer to such types. When marshaling, embedded fields from a pointer type are omitted if it is nil. Embedded fields of type jsontext.Value and map[~string]T are called “embedded fallbacks” as they can represent all possible JSON object members not directly handled by the parent struct. Only one embedded fallback field may be specified in a struct, while many non-fallback fields may be specified. This option must not be specified with any other option (including the JSON name).

The "omitzero" and "omitempty" options behave similarly. The former is defined in terms of the Go type system, while the latter in terms of the JSON type system. Consequently they behave differently in some circumstances. For example, only a nil slice or map is omitted under "omitzero", while an empty slice or map is omitted under "omitempty" regardless of nilness. The "omitzero" option is useful for types with a well-defined zero value (e.g., net/netip.Addr) or have an IsZero method (e.g., time.Time.IsZero).

Every Go struct corresponds to a list of JSON-representable fields which is constructed by performing a breadth-first search over all struct fields (excluding unexported or ignored fields), where the search recursively descends into embedded structs. The set of non-embedded fields in a struct must have unique JSON names. If multiple fields all have the same JSON name, then the one at shallowest depth takes precedence and the other fields at deeper depths are excluded from the list of JSON-representable fields. If multiple fields at the shallowest depth have the same JSON name, but exactly one is explicitly tagged with a JSON name, then that field takes precedence and all others are excluded from the list. This is analogous to Go visibility rules for struct field selection with embedded struct types.

Marshaling or unmarshaling a non-empty struct without any JSON-representable fields results in a SemanticError. Unexported fields must not have any `json` tags except for `json:"-"`.

Security Considerations

JSON is frequently used as a data interchange format to communicate between different systems, possibly implemented in different languages. For interoperability and security reasons, it is important that all implementations agree upon the semantic meaning of the data.

For example, suppose we have two micro-services. The first service is responsible for authenticating a JSON request, while the second service is responsible for executing the request, assuming that it was authenticated. If an attacker were able to maliciously craft a JSON request such that both services believe that the same request is from different users, it could bypass the authenticator with valid credentials for one user, but maliciously perform an action on behalf of a different user.

According to RFC 8259, there unfortunately exist many JSON texts that are syntactically valid but semantically ambiguous. For example, the standard does not define how to interpret duplicate names within an object.

The v1 encoding/json and encoding/json/v2 packages interpret some inputs in different ways. In particular:

  • The standard specifies that JSON must be encoded using UTF-8. By default, v1 replaces invalid bytes of UTF-8 in JSON strings with the Unicode replacement character, while v2 rejects inputs with invalid UTF-8. To change the default, specify the jsontext.AllowInvalidUTF8 option. The replacement of invalid UTF-8 is a form of data corruption that alters the precise meaning of strings.

  • The standard does not specify a particular behavior when duplicate names are encountered within a JSON object, which means that different implementations may behave differently. By default, v1 allows for the presence of duplicate names, while v2 rejects duplicate names. To change the default, specify the jsontext.AllowDuplicateNames option. If allowed, object members are processed in the order they are observed, meaning that later values will replace or be merged into prior values, depending on the Go value type.

  • The standard defines a JSON object as an unordered collection of name/value pairs. While ordering can be observed through the underlying jsontext API, both v1 and v2 generally avoid exposing the ordering. No application should semantically depend on the order of object members. Allowing duplicate names is a vector through which ordering of members can accidentally be observed and depended upon.

  • The standard suggests that JSON object names are typically compared based on equality of the sequence of Unicode code points, which implies that comparing names is often case-sensitive. When unmarshaling a JSON object into a Go struct, by default, v1 uses a (loose) case-insensitive match on the name, while v2 uses a (strict) case-sensitive match on the name. To change the default, specify the MatchCaseInsensitiveNames option. The use of case-insensitive matching provides another vector through which duplicate names can occur. Allowing case-insensitive matching means that v1 or v2 might interpret JSON objects differently from most other JSON implementations (which typically use a case-sensitive match).

  • The standard does not specify a particular behavior when an unknown name in a JSON object is encountered. When unmarshaling a JSON object into a Go struct, by default both v1 and v2 ignore unknown names and their corresponding values. To change the default, specify the RejectUnknownMembers option.

  • The standard suggests that implementations may use a float64 to represent a JSON number. Consequently, large JSON integers may lose precision when stored as a floating-point type. Both v1 and v2 correctly preserve precision when marshaling and unmarshaling a concrete integer type. However, even if v1 and v2 preserve precision for concrete types, other JSON implementations may not be able to preserve precision for outputs produced by v1 or v2. The `string` tag option can be used to specify that an integer type is to be quoted within a JSON string to avoid loss of precision. Furthermore, v1 and v2 may still lose precision when unmarshaling into an any interface value, where unmarshal uses a float64 by default to represent a JSON number. To change the default, specify the WithUnmarshalers option with a custom unmarshaler that pre-populates the interface value with a concrete Go type that can preserve precision.

RFC 8785 specifies a canonical form for any JSON text, which explicitly defines specific behaviors that RFC 8259 leaves undefined. In theory, if a text can successfully jsontext.Value.Canonicalize without changing the semantic meaning of the data, then it provides a greater degree of confidence that the data is more secure and interoperable.

The v2 API generally chooses more secure defaults than v1, but care should still be taken with large integers or unknown members.

Example (CaseSensitivity)

Unmarshal matches JSON object names with Go struct fields using a case-sensitive match, but can be configured to use a case-insensitive match with the "case:ignore" option. This permits unmarshaling from inputs that use naming conventions such as camelCase, snake_case, or kebab-case.

[{false} {true} {false} {false} {false} {false} {false} {false} {false}]
[{true} {true} {true} {true} {true} {true} {true} {true} {false}]

Example (EmbeddedFields)

JSON objects can be embedded within a parent object similar to how Go structs can be embedded within a parent struct. The JSON embedding rules are similar to those of Go embedding, but operates upon the JSON namespace.

{
	"ID": "",
	"Type": 0,
	"User": "",
	"uuid": "",
	"other": {
		"Cost": 0
	}
}

Example (FieldNames)

By default, JSON object names for Go struct fields are derived from the Go field name, but may be specified in the `json` tag. Due to JSON's heritage in JavaScript, the most common naming convention used for JSON object names is camelCase.

{
	"GoName": null,
	"jsonName": null,
	"Option": null
}

Example (OmitFields)

Go struct fields can be omitted from the output depending on either the input Go value or the output JSON encoding of the value. The "omitzero" option omits a field if it is the zero Go value or implements a "IsZero() bool" method that reports true. The "omitempty" option omits a field if it encodes as an empty JSON value, which we define as a JSON null or empty JSON string, object, or array. In many cases, the behavior of "omitzero" and "omitempty" are equivalent. If both provide the desired effect, then using "omitzero" is preferred.

OmitZero: {
	"Struct": {},
	"Slice": [],
	"Map": {},
	"Pointer": "",
	"Interface": null
}
OmitEmpty: {
	"Bool": false,
	"Int": 0,
	"Time": "0001-01-01T00:00:00Z"
}

Example (OrderedObject)

The exact order of JSON object can be preserved through the use of a specialized type that implements [MarshalerTo] and [UnmarshalerFrom].

{
	"fizz": "buzz",
	"hello": "world",
	"fizz": "wuzz"
}

Example (ProtoJSON)

Some Go types have a custom JSON representation where the implementation is delegated to some external package. Consequently, the "json" package will not know how to use that external implementation. For example, the [google.golang.org/protobuf/encoding/protojson] package implements JSON for all [google.golang.org/protobuf/proto.Message] types. [WithMarshalers] and [WithUnmarshalers] can be used to configure "json" and "protojson" to cooperate together.

Example (ServeHTTP)

When implementing HTTP endpoints, it is common to be operating with an [io.Reader] and an [io.Writer]. The [MarshalWrite] and [UnmarshalRead] functions assist in operating on such input/output types. [UnmarshalRead] reads the entirety of the [io.Reader] to ensure that [io.EOF] is encountered without any unexpected bytes after the top-level JSON value.

Example (TextMarshal)

If a type implements [encoding.TextMarshaler] and/or [encoding.TextUnmarshaler], then the MarshalText and UnmarshalText methods are used to encode/decode the value to/from a JSON string.

{
	"192.168.0.100": "carbonite",
	"192.168.0.101": "obsidian",
	"192.168.0.102": "diamond"
}

Index ▾

Variables
func GetOption[T any](opts Options, setter func(T) Options) (T, bool)
func Marshal(in any, opts ...Options) (out []byte, err error)
func MarshalEncode(out *jsontext.Encoder, in any, opts ...Options) (err error)
func MarshalWrite(out io.Writer, in any, opts ...Options) (err error)
func Unmarshal(in []byte, out any, opts ...Options) (err error)
func UnmarshalDecode(in *jsontext.Decoder, out any, opts ...Options) (err error)
func UnmarshalRead(in io.Reader, out any, opts ...Options) (err error)
type Marshaler
type MarshalerTo
type Marshalers
    func JoinMarshalers(ms ...*Marshalers) *Marshalers
    func MarshalFunc[T any](fn func(T) ([]byte, error)) *Marshalers
    func MarshalToFunc[T any](fn func(*jsontext.Encoder, T) error) *Marshalers
type Options
    func DefaultOptionsV2() Options
    func Deterministic(v bool) Options
    func FormatNilMapAsNull(v bool) Options
    func FormatNilSliceAsNull(v bool) Options
    func JoinOptions(srcs ...Options) Options
    func MatchCaseInsensitiveNames(v bool) Options
    func OmitZeroStructFields(v bool) Options
    func RejectUnknownMembers(v bool) Options
    func StringifyNumbers(v bool) Options
    func WithMarshalers(v *Marshalers) Options
    func WithUnmarshalers(v *Unmarshalers) Options
type SemanticError
    func (e *SemanticError) Error() string
    func (e *SemanticError) Unwrap() error
type Unmarshaler
type UnmarshalerFrom
type Unmarshalers
    func JoinUnmarshalers(us ...*Unmarshalers) *Unmarshalers
    func UnmarshalFromFunc[T any](fn func(*jsontext.Decoder, T) error) *Unmarshalers
    func UnmarshalFunc[T any](fn func([]byte, T) error) *Unmarshalers

Package files

arshal.go arshal_any.go arshal_default.go arshal_embedded.go arshal_funcs.go arshal_methods.go arshal_time.go doc.go errors.go fields.go fold.go intern.go options.go

Variables

ErrUnknownName indicates that a JSON object member could not be unmarshaled because the name is not known to the target Go struct. This error is directly wrapped within a SemanticError when produced.

The name of an unknown JSON object member can be extracted as:

err := ...
serr, ok := errors.AsType[*json.SemanticError](err)
if ok && serr.Err == json.ErrUnknownName {
	ptr := serr.JSONPointer // JSON pointer to unknown name
	name := ptr.LastToken() // unknown name itself
	...
}

This error is only returned if RejectUnknownMembers is true.

var ErrUnknownName = errors.New("unknown object member name")

func GetOption

func GetOption[T any](opts Options, setter func(T) Options) (T, bool)

GetOption returns the value stored in opts with the provided setter, reporting whether the value is present. If not present, the returned value is the zero value for type T.

Example usage:

v, ok := json.GetOption(opts, json.Deterministic)

Options are most commonly introspected to alter the JSON representation of MarshalerTo.MarshalJSONTo and UnmarshalerFrom.UnmarshalJSONFrom methods, and MarshalToFunc and UnmarshalFromFunc functions. In such cases, the presence bit should generally be ignored.

func Marshal 1.27

func Marshal(in any, opts ...Options) (out []byte, err error)

Marshal serializes a Go value as a []byte according to the provided marshal and encode options (while ignoring unmarshal or decode options). It does not terminate the output with a newline.

Type-specific marshal functions and methods take precedence over the default representation of a value. Functions or methods that operate on *T are only called when encoding a value of type T (by taking its address) or a non-nil value of *T. Marshal ensures that a value is always addressable (by copying the value if necessary) so that these functions and methods can be consistently called. For performance, it is recommended that Marshal be passed a non-nil pointer to the value.

The input value is encoded as JSON according to the following rules:

Most Go types have a default JSON representation as follows:

JSON cannot represent cyclic data structures and Marshal does not handle them.

Example (Multiline)

Use [jsontext.Multiline] to create multiline, idented output for more readable output for human consumption. See [jsontext.Multiline] for additional options that customize the multiline output.

{
	"Name": "Oliver",
	"Species": "Dog",
	"Breed": "Goldendoodle"
}

func MarshalEncode 1.27

func MarshalEncode(out *jsontext.Encoder, in any, opts ...Options) (err error)

MarshalEncode serializes a Go value into an jsontext.Encoder according to the provided marshal or encode options (while ignoring unmarshal or decode options). The options provided take precedence over options already applied on the jsontext.Encoder and only apply for the duration of the marshal call.

See Marshal for details about the conversion of a Go value into JSON.

func MarshalWrite 1.27

func MarshalWrite(out io.Writer, in any, opts ...Options) (err error)

MarshalWrite serializes a Go value into an io.Writer according to the provided marshal and encode options (while ignoring unmarshal or decode options). It does not terminate the output with a newline. See Marshal for details about the conversion of a Go value into JSON.

func Unmarshal 1.27

func Unmarshal(in []byte, out any, opts ...Options) (err error)

Unmarshal decodes a []byte input into a Go value according to the provided unmarshal and decode options (while ignoring marshal or encode options). The input must be a single JSON value with optional whitespace interspersed. The output must be a non-nil pointer.

Type-specific unmarshal functions and methods take precedence over the default representation of a value. Functions or methods that operate on *T are only called when decoding a value of type T (by taking its address) or a non-nil value of *T. Unmarshal ensures that a value is always addressable (by copying the value if necessary) so that these functions and methods can be consistently called. If a value must be shallow copied to call a pointer-receiver Unmarshaler, UnmarshalerFrom, or encoding.TextUnmarshaler method, then any mutations performed by the method are shallow copied back into the destination value.

The input is decoded into the output according to the following rules:

Most Go types have a default JSON representation. A JSON null may be decoded into every supported Go value where it is equivalent to storing the zero value of the Go value. If the input JSON kind is not handled by the current Go value type, then this fails with a SemanticError. Unless otherwise specified, the decoded value replaces any pre-existing value.

The representation of each type is as follows:

In general, unmarshaling follows merge semantics (similar to RFC 7396) where the decoded Go value replaces the destination value for any JSON kind other than an object. For JSON objects, the input object is merged into the destination value where matching object members recursively apply merge semantics.

func UnmarshalDecode 1.27

func UnmarshalDecode(in *jsontext.Decoder, out any, opts ...Options) (err error)

UnmarshalDecode deserializes a Go value from a jsontext.Decoder according to the provided unmarshal or decode options (while ignoring marshal or encode options). The options provided take precedence over options already applied on the jsontext.Decoder and only apply for the duration of the unmarshal call.

The input may be a stream of zero or more JSON values. UnmarshalDecode unmarshals only the next JSON value in the stream. If there are no more top-level JSON values, it reports io.EOF. The output must be a non-nil pointer. See Unmarshal for details about the conversion of JSON into a Go value.

Example (Stream)

UnmarshalDecode can be used to unmarshal a stream of whitespace-delimited JSON values.

Platypus: Monotremata
Quoll: Dasyuromorphia
Gopher: Rodentia

func UnmarshalRead 1.27

func UnmarshalRead(in io.Reader, out any, opts ...Options) (err error)

UnmarshalRead deserializes a Go value from an io.Reader according to the provided unmarshal and decode options (while ignoring marshal or encode options). The input must be a single JSON value with optional whitespace interspersed. It consumes the entirety of io.Reader until io.EOF is encountered, without reporting an error for EOF. The output must be a non-nil pointer. See Unmarshal for details about the conversion of JSON into a Go value.

type Marshaler 1.27

Marshaler is implemented by types that can marshal themselves. It is recommended that types implement MarshalerTo unless the implementation is trying to avoid directly depending on the "jsontext" package.

Implementations should return a buffer that is safe for the caller to retain and potentially mutate.

Implementations must not return errors.ErrUnsupported.

If the returned error is a SemanticError, then unpopulated fields of the error may be populated by json with additional context. Errors of other types are wrapped within a SemanticError.

Implementations should assume Deterministic is true and return deterministic output.

type Marshaler interface {
    MarshalJSON() ([]byte, error)
}

type MarshalerTo 1.27

MarshalerTo is implemented by types that can marshal themselves. It is recommended that types implement MarshalerTo instead of Marshaler since it is both more performant and more flexible. If a type implements both Marshaler and MarshalerTo, then MarshalerTo takes precedence. In such a case, both implementations should aim to have equivalent behavior for the default marshal options.

The implementation must write only one JSON value to the Encoder. Alternatively, it may return errors.ErrUnsupported without mutating the Encoder. The "json" package calling the method will use the next available JSON representation for the receiver type, as described in Marshal. Implementations must not retain the pointer to jsontext.Encoder.

If the returned error is a SemanticError, then unpopulated fields of the error may be populated by json with additional context. Errors of other types are wrapped within a SemanticError, except for IO errors.

The MarshalJSONTo method should not be called directly as it may return sentinel errors that need special handling. Users should instead call MarshalEncode, which handles such cases.

Implementations should inspect the marshal options from jsontext.Encoder.Options and adjust behavior to respect the options as necessary.

The following options may be relevant to MarshalerTo implementations:

- Deterministic: if the implementation may produce non-deterministic output - StringifyNumbers: if the type is represented as a JSON number

Several options, such as FormatNilSliceAsNull, apply only to native Go types. Thus, these options are typically not directly relevant to MarshalerTo implementations. However, types representing a composite type should marshal contained types using MarshalEncode to ensure these options apply to the contained types. Similarly, WithMarshalers may influence marshaling of any contained type within a composite type.

All other options are automatically handled outside of the MarshalerTo implementation, and thus are not relevant to implementations.

type MarshalerTo interface {
    MarshalJSONTo(*jsontext.Encoder) error
}

Example

Custom types may define custom marshal behavior with [MarshalerTo].

[
	1,
	2,
	3
]

type Marshalers 1.27

Marshalers is a list of functions that may override the marshal behavior of specific types. Populate WithMarshalers to use it with Marshal, MarshalWrite, or MarshalEncode. A nil *Marshalers is equivalent to an empty list. There are no exported fields or methods on Marshalers.

type Marshalers = typedMarshalers

func JoinMarshalers 1.27

func JoinMarshalers(ms ...*Marshalers) *Marshalers

JoinMarshalers constructs a flattened list of marshal functions. If multiple functions in the list are applicable for a value of a given type, then those earlier in the list take precedence over those that come later. If a function returns errors.ErrUnsupported, then the next applicable function is called, otherwise the default marshaling behavior is used.

For example:

m1 := JoinMarshalers(f1, f2)
m2 := JoinMarshalers(f0, m1, f3)     // equivalent to m3
m3 := JoinMarshalers(f0, f1, f2, f3) // equivalent to m2

func MarshalFunc

func MarshalFunc[T any](fn func(T) ([]byte, error)) *Marshalers

MarshalFunc constructs a type-specific marshaler that specifies how to marshal values of type T. T can be any type except a named pointer. The function is always provided with a non-nil pointer value if T is an interface or pointer type.

Implementations must follow the requirements of Marshaler.

Implementations must not retain the value of T.

func MarshalToFunc

func MarshalToFunc[T any](fn func(*jsontext.Encoder, T) error) *Marshalers

MarshalToFunc constructs a type-specific marshaler that specifies how to marshal values of type T. T can be any type except a named pointer. The function is always provided with a non-nil pointer value if T is an interface or pointer type.

Implementations must follow the requirements of MarshalerTo.

Implementations must not retain the pointer to jsontext.Encoder or the value of T.

type Options 1.27

Options configure Marshal, MarshalWrite, MarshalEncode, Unmarshal, UnmarshalRead, and UnmarshalDecode with specific features. Each function takes in a variadic list of options, where properties set in later options override the value of previously set properties.

The Options type is identical to encoding/json.Options and encoding/json/jsontext.Options. Options from the other packages can be used interchangeably with functionality in this package.

An Options value represents either a single option or a set of options. It can be thought of as a Go map of option properties (even though the underlying implementation avoids Go maps for performance).

The constructors (e.g., Deterministic) return a value for a single option:

opt := Deterministic(true)

which is analogous to creating a single entry map:

opt := Options{"Deterministic": true}

JoinOptions composes multiple options values together:

out := JoinOptions(opts...)

which is analogous to making a new map and copying the options over:

out := make(Options)
for _, m := range opts {
	for k, v := range m {
		out[k] = v
	}
}

GetOption looks up the value of an options parameter:

v, ok := GetOption(opts, Deterministic)

which is analogous to a Go map lookup:

v, ok := Options["Deterministic"]

There is a single Options type, which is used with both marshal and unmarshal. Some options affect both operations, while others only affect one operation:

Options that do not affect a particular operation are ignored.

type Options = jsonopts.Options

func DefaultOptionsV2 1.27

func DefaultOptionsV2() Options

DefaultOptionsV2 is the full set of all options that define v2 semantics. It is equivalent to the set of options in encoding/json.DefaultOptionsV1 all being set to false. All other options are not present.

func Deterministic 1.27

func Deterministic(v bool) Options

Deterministic specifies that marshaling the same input value will always serialize as the same output bytes.

For example, Go maps are marshaled sorted by key.

For native Go types, Determinism is guaranteed across different instances of identical binaries, but not across different builds of a program (such as different source or toolchain version, different GOOS/GOARCH, different build flags).

A Go type with a custom marshaler should also respect the Deterministic option and serialize deterministically if it is true.

This only affects marshaling and is ignored when unmarshaling.

func FormatNilMapAsNull 1.27

func FormatNilMapAsNull(v bool) Options

FormatNilMapAsNull specifies that a nil Go map should marshal as a JSON null instead of the default representation as an empty JSON object.

This only affects marshaling and is ignored when unmarshaling.

func FormatNilSliceAsNull 1.27

func FormatNilSliceAsNull(v bool) Options

FormatNilSliceAsNull specifies that a nil Go slice should marshal as a JSON null instead of the default representation as an empty JSON array (or an empty JSON string in the case of ~[]byte).

This only affects marshaling and is ignored when unmarshaling.

func JoinOptions 1.27

func JoinOptions(srcs ...Options) Options

JoinOptions coalesces the provided list of options into a single Options. Properties set in later options override the value of previously set properties.

func MatchCaseInsensitiveNames 1.27

func MatchCaseInsensitiveNames(v bool) Options

MatchCaseInsensitiveNames specifies that JSON object members are matched against Go struct fields using a case-insensitive match of the name. If a name matches multiple fields, the field whose name matches exactly is chosen. If there is none, an error is reported. Go struct fields explicitly marked with `case:strict` or `case:ignore` always use case-sensitive (or case-insensitive) name matching, regardless of the value of this option.

This affects either marshaling or unmarshaling.

Matching names case-insensitively also affects duplicate name detection (assuming jsontext.AllowDuplicateNames is false) since variations of the same name may match the same Go struct field. For example, when unmarshaling, the names "foo" and "Foo" may both match the same Go struct field and therefore be considered a duplicate name. When marshaling, normally it is impossible for any two Go struct fields to serialize in a way where they unmarshal into the same Go struct field since they all have unique exact names. However, it is possible for an embedded fallback to contain a name that also matches the name for a Go struct field, resulting in a duplicate name error.

func OmitZeroStructFields 1.27

func OmitZeroStructFields(v bool) Options

OmitZeroStructFields specifies that zero-valued fields of Go struct should be omitted from the marshaled output. A value is considered zero if its type has an "IsZero() bool" method that returns true, or if it lacks such a method and the value is a Go zero value. This option is equivalent to specifying the `omitzero` tag option on every field in a Go struct.

This only affects marshaling and is ignored when unmarshaling.

func RejectUnknownMembers 1.27

func RejectUnknownMembers(v bool) Options

RejectUnknownMembers specifies that unknown members should be rejected when unmarshaling a JSON object.

This only affects unmarshaling and is ignored when marshaling.

func StringifyNumbers 1.27

func StringifyNumbers(v bool) Options

StringifyNumbers specifies that types that would normally be encoded as a JSON number instead be encoded as a JSON string containing the equivalent JSON number value. When unmarshaling, the value is parsed from a JSON string containing the JSON number without any surrounding whitespace.

Specifying the `string` tag option on a Go struct field applies this option to the top-level JSON value for that field. When applied via the `string` tag option, StringifyNumbers option does not recursively apply to nested JSON numbers within a JSON object or array.

Like all options, explicitly specifying this option in a call to Marshal, Unmarshal, etc, will apply recursively.

A Go type with custom marshal/unmarshal that represents a JSON number should respect the StringifyNumbers option and if specified serialize as a JSON number within a JSON string. Custom marshal/unmarshal should handle nested JSON objects using MarshalEncode/UnmarshalDecode, which will automatically apply the non-recursive `string` tag option behavior.

According to RFC 8259, section 6, a JSON implementation may choose to limit the representation of a JSON number to an IEEE 754 binary64 value. This may cause decoders to lose precision for int64 and uint64 types. Quoting JSON numbers as a JSON string preserves the exact precision.

This affects either marshaling or unmarshaling.

func WithMarshalers 1.27

func WithMarshalers(v *Marshalers) Options

WithMarshalers specifies a list of type-specific marshalers to use, which can be used to override the default marshal behavior for values of particular types.

This only affects marshaling and is ignored when unmarshaling.

Example (Errors)

Many error types are not serializable since they tend to be Go structs without any exported fields (e.g., errors constructed with [errors.New]). Some applications, may desire to marshal an error as a JSON string even if these errors cannot be unmarshaled.

[
	{
		"Result": "Oranges are a good source of Vitamin C."
	},
	{
		"Error": "strconv.ParseUint: parsing \"-1234\": invalid syntax"
	},
	{
		"Error": "internal server error"
	}
]

func WithUnmarshalers 1.27

func WithUnmarshalers(v *Unmarshalers) Options

WithUnmarshalers specifies a list of type-specific unmarshalers to use, which can be used to override the default unmarshal behavior for values of particular types.

This only affects unmarshaling and is ignored when marshaling.

Example (RawNumber)

In some applications, the exact precision of JSON numbers needs to be preserved when unmarshaling. This can be accomplished using a type-specific unmarshal function that intercepts all any types and pre-populates the interface value with a [jsontext.Value], which can represent a JSON number exactly.

[false 1e-1000 3.141592653589793238462643383279 1e+1000 true]

Example (RecordOffsets)

When using JSON for parsing configuration files, the parsing logic often needs to report an error with a line and column indicating where in the input an error occurred.

3:3: source and destination must both be specified

type SemanticError 1.27

SemanticError describes an error determining the meaning of JSON data as Go data, or vice versa.

If a Marshaler, MarshalerTo, Unmarshaler, or UnmarshalerFrom method returns a SemanticError when called by the json package, then the ByteOffset, JSONPointer, and GoType fields are automatically populated by the calling context if they are the zero value.

The contents of this error as produced by this package may change over time.

type SemanticError struct {

    // ByteOffset indicates that an error occurred at or after this byte offset.
    ByteOffset int64
    // JSONPointer indicates that an error occurred within this JSON value
    // as indicated using the JSON Pointer notation (see RFC 6901).
    JSONPointer jsontext.Pointer

    // JSONKind is the JSON kind that could not be handled.
    JSONKind jsontext.Kind // may be zero if unknown
    // JSONValue is the JSON number or string that could not be unmarshaled.
    // It is not populated during marshaling.
    JSONValue jsontext.Value // may be nil if irrelevant or unknown
    // GoType is the Go type that could not be handled.
    GoType reflect.Type // may be nil if unknown

    // Err is the underlying error.
    Err error // may be nil
    // contains filtered or unexported fields
}

func (*SemanticError) Error 1.27

func (e *SemanticError) Error() string

func (*SemanticError) Unwrap 1.27

func (e *SemanticError) Unwrap() error

type Unmarshaler 1.27

Unmarshaler is implemented by types that can unmarshal themselves. It is recommended that types implement UnmarshalerFrom unless the implementation is trying to avoid a direct dependency on the "jsontext" package.

The input can be assumed to be a valid encoding of a JSON value if called from unmarshal functionality in this package. It is recommended that UnmarshalJSON implement merge semantics when unmarshaling into a pre-populated value, as described in Unmarshal.

Implementations must not retain or mutate the input []byte.

Implementations must not return errors.ErrUnsupported.

If the returned error is a SemanticError, then unpopulated fields of the error may be populated by json with additional context. Errors of other types are wrapped within a SemanticError.

type Unmarshaler interface {
    UnmarshalJSON([]byte) error
}

type UnmarshalerFrom 1.27

UnmarshalerFrom is implemented by types that can unmarshal themselves. It is recommended that types implement UnmarshalerFrom instead of Unmarshaler since this is both more performant and more flexible. If a type implements both Unmarshaler and UnmarshalerFrom, then UnmarshalerFrom takes precedence. In such a case, both implementations should aim to have equivalent behavior for the default unmarshal options.

The implementation must read only one JSON value from the Decoder. It is recommended that UnmarshalJSONFrom implement merge semantics when unmarshaling into a pre-populated value, as described in Unmarshal. Alternatively, it may return errors.ErrUnsupported without mutating the Decoder. The "json" package calling the method will use the next available JSON representation for the receiver type. Implementations must not retain the pointer to jsontext.Decoder.

If the returned error is a SemanticError, then unpopulated fields of the error may be populated by json with additional context. Errors of other types are wrapped within a SemanticError, except for [jsontext.SyntacticError]s and IO errors.

The UnmarshalJSONFrom method should not be called directly as it may return sentinel errors that need special handling. Users should instead call UnmarshalDecode, which handles such cases.

Implementations should inspect the unmarshal options from jsontext.Decoder.Options and adjust behavior to respect the options as necessary.

The following options may be relevant to UnmarshalerFrom implementations:

- StringifyNumbers: if the type is represented as a JSON number

Several options, such as FormatNilSliceAsNull, apply only to native Go types. Thus, these options are typically not directly relevant to UnmarshalerFrom implementations. However, types representing a composite type should unmarshal contained types using UnmarshalDecode to ensure these options apply to the contained types. Similarly, WithUnmarshalers may influence unmarshaling of any contained type within a composite type.

All other options are automatically handled outside of the UnmarshalerFrom implementation, and thus are not relevant to implementations.

type UnmarshalerFrom interface {
    UnmarshalJSONFrom(*jsontext.Decoder) error
}

Example

Custom types may define custom unmarshal behavior with [UnmarshalerFrom].

map[1:{} 2:{} 3:{}]

type Unmarshalers 1.27

Unmarshalers is a list of functions that may override the unmarshal behavior of specific types. Populate WithUnmarshalers to use it with Unmarshal, UnmarshalRead, or UnmarshalDecode. A nil *Unmarshalers is equivalent to an empty list. There are no exported fields or methods on Unmarshalers.

type Unmarshalers = typedUnmarshalers

func JoinUnmarshalers 1.27

func JoinUnmarshalers(us ...*Unmarshalers) *Unmarshalers

JoinUnmarshalers constructs a flattened list of unmarshal functions. If multiple functions in the list are applicable for a value of a given type, then those earlier in the list take precedence over those that come later. If a function returns errors.ErrUnsupported, then the next applicable function is called, otherwise the default unmarshaling behavior is used.

For example:

u1 := JoinUnmarshalers(f1, f2)
u2 := JoinUnmarshalers(f0, u1, f3)     // equivalent to u3
u3 := JoinUnmarshalers(f0, f1, f2, f3) // equivalent to u2

func UnmarshalFromFunc

func UnmarshalFromFunc[T any](fn func(*jsontext.Decoder, T) error) *Unmarshalers

UnmarshalFromFunc constructs a type-specific unmarshaler that specifies how to unmarshal values of type T. T must be an unnamed pointer or an interface type. The function is always provided with a non-nil pointer value.

Implementations must follow the requirements of UnmarshalerFrom.

Implementations must not retain the pointer to jsontext.Decoder or the value of T.

func UnmarshalFunc

func UnmarshalFunc[T any](fn func([]byte, T) error) *Unmarshalers

UnmarshalFunc constructs a type-specific unmarshaler that specifies how to unmarshal values of type T. T must be an unnamed pointer or an interface type. The function is always provided with a non-nil pointer value.

Implementations must follow the requirements of Unmarshaler.

Implementations must not retain the value of T.