Involved Source Filesarshal.goarshal_any.goarshal_default.goarshal_funcs.goarshal_inlined.goarshal_methods.goarshal_time.go 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.
[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. JSON names containing commas or quotes,
or names identical to "" or "-", can be specified using
a single-quoted string literal, where the syntax is identical to
the Go grammar for a double-quoted string literal,
but instead uses single quotes as the delimiters.
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 numeric types to be encoded as a JSON number
within a JSON string, and to be decoded from a JSON string
containing the JSON number without any surrounding whitespace.
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
where dashes and underscores are also ignored. If multiple fields match,
the first declared field in breadth-first order takes precedence.
The 'strict' value specifies that matching is case-sensitive.
This takes precedence over the [MatchCaseInsensitiveNames] option.
- inline: The "inline" option specifies that
the JSON representable content of this field type is to be promoted
as if they were specified in the parent struct.
It is the JSON equivalent of Go struct embedding.
A Go embedded field is implicitly inlined unless an explicit JSON name
is specified. The inlined 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,
inlined fields from a pointer type are omitted if it is nil.
Inlined fields of type [jsontext.Value] and map[~string]T are called
“inlined fallbacks” as they can represent all possible
JSON object members not directly handled by the parent struct.
Only one inlined 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).
- unknown: The "unknown" option is a specialized variant
of the inlined fallback to indicate that this Go struct field
contains any number of unknown JSON object members. The field type must
be a [jsontext.Value], map[~string]T, or an unnamed pointer to such types.
If [DiscardUnknownMembers] is specified when marshaling,
the contents of this field are ignored.
If [RejectUnknownMembers] is specified when unmarshaling,
any unknown object members are rejected regardless of whether
an inlined fallback with the "unknown" option exists. This option
must not be specified with any other option (including the JSON name).
- format: The "format" option specifies a format flag
used to specialize the formatting of the field value.
The option is a key-value pair specified as "format:value" where
the value must be either a literal consisting of letters and numbers
(e.g., "format:RFC3339") or a single-quoted string literal
(e.g., "format:'2006-01-02'"). The interpretation of the format flag
is determined by the struct field type.
The "omitzero" and "omitempty" options are mostly semantically identical.
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 inlined structs.
The set of non-inlined 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:"-"`.errors.gofields.gofold.gointern.gooptions.go
Code Examples
{
response := []struct {
Result string `json:",omitzero"`
Error error `json:",omitzero"`
}{
{Result: "Oranges are a good source of Vitamin C."},
{Error: &strconv.NumError{Func: "ParseUint", Num: "-1234", Err: strconv.ErrSyntax}},
{Error: &os.PathError{Op: "ReadFile", Path: "/path/to/secret/file", Err: os.ErrPermission}},
}
b, err := json.Marshal(&response,
json.WithMarshalers(json.JoinMarshalers(
json.MarshalToFunc(func(enc *jsontext.Encoder, err *strconv.NumError) error {
return enc.WriteToken(jsontext.String(err.Error()))
}),
json.MarshalFunc(func(error) ([]byte, error) {
return []byte(`"internal server error"`), nil
}),
)),
jsontext.Multiline(true))
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
{
// Input with JSON numbers beyond the representation of a float64.
const input = `[false, 1e-1000, 3.141592653589793238462643383279, 1e+1000, true]`
var value any
err := json.Unmarshal([]byte(input), &value,
json.WithUnmarshalers(
json.UnmarshalFromFunc(func(dec *jsontext.Decoder, val *any) error {
if dec.PeekKind() == '0' {
*val = jsontext.Value(nil)
}
return json.SkipFunc
}),
))
if err != nil {
log.Fatal(err)
}
fmt.Println(value)
want := []any{false, jsontext.Value("1e-1000"), jsontext.Value("3.141592653589793238462643383279"), jsontext.Value("1e+1000"), true}
if !reflect.DeepEqual(value, want) {
log.Fatalf("value mismatch:\ngot %v\nwant %v", value, want)
}
}
{
// Hypothetical configuration file.
const input = `[
{"Source": "192.168.0.100:1234", "Destination": "192.168.0.1:80"},
{"Source": "192.168.0.251:4004"},
{"Source": "192.168.0.165:8080", "Destination": "0.0.0.0:80"}
]`
type Tunnel struct {
Source netip.AddrPort
Destination netip.AddrPort
// ByteOffset is populated during unmarshal with the byte offset
// within the JSON input of the JSON object for this Go struct.
ByteOffset int64 `json:"-"` // metadata to be ignored for JSON serialization
}
var tunnels []Tunnel
err := json.Unmarshal([]byte(input), &tunnels,
json.WithUnmarshalers(
json.UnmarshalFromFunc(func(dec *jsontext.Decoder, tunnel *Tunnel) error {
dec.PeekKind()
unread := dec.UnreadBuffer()
n := len(unread) - len(bytes.TrimLeft(unread, " \n\r\t,:"))
tunnel.ByteOffset = dec.InputOffset() + int64(n)
return json.SkipFunc
}),
))
if err != nil {
log.Fatal(err)
}
lineColumn := func(input string, offset int) (line, column int) {
line = 1 + strings.Count(input[:offset], "\n")
column = 1 + offset - (strings.LastIndex(input[:offset], "\n") + len("\n"))
return line, column
}
for _, tunnel := range tunnels {
if !tunnel.Source.IsValid() || !tunnel.Destination.IsValid() {
line, column := lineColumn(input, int(tunnel.ByteOffset))
fmt.Printf("%d:%d: source and destination must both be specified", line, column)
}
}
}
{
// JSON input using various naming conventions.
const input = `[
{"firstname": true},
{"firstName": true},
{"FirstName": true},
{"FIRSTNAME": true},
{"first_name": true},
{"FIRST_NAME": true},
{"first-name": true},
{"FIRST-NAME": true},
{"unknown": true}
]`
// Without "case:ignore", Unmarshal looks for an exact match.
var caseStrict []struct {
X bool `json:"firstName"`
}
if err := json.Unmarshal([]byte(input), &caseStrict); err != nil {
log.Fatal(err)
}
fmt.Println(caseStrict)
// With "case:ignore", Unmarshal looks first for an exact match,
// then for a case-insensitive match if none found.
var caseIgnore []struct {
X bool `json:"firstName,case:ignore"`
}
if err := json.Unmarshal([]byte(input), &caseIgnore); err != nil {
log.Fatal(err)
}
fmt.Println(caseIgnore)
}
{
var value struct {
// This field is explicitly ignored with the special "-" name.
Ignored any `json:"-"`
// No JSON name is not provided, so the Go field name is used.
GoName any
// A JSON name is provided without any special characters.
JSONName any `json:"jsonName"`
// No JSON name is not provided, so the Go field name is used.
Option any `json:",case:ignore"`
// An empty JSON name specified using an single-quoted string literal.
Empty any `json:"''"`
// A dash JSON name specified using an single-quoted string literal.
Dash any `json:"'-'"`
// A comma JSON name specified using an single-quoted string literal.
Comma any `json:"','"`
// JSON name with quotes specified using a single-quoted string literal.
Quote any `json:"'\"\\''"`
// An unexported field is always ignored.
unexported any
}
b, err := json.Marshal(value)
if err != nil {
log.Fatal(err)
}
(*jsontext.Value)(&b).Indent()
fmt.Println(string(b))
}
{
value := struct {
BytesBase64 []byte `json:",format:base64"`
BytesHex [8]byte `json:",format:hex"`
BytesArray []byte `json:",format:array"`
FloatNonFinite float64 `json:",format:nonfinite"`
MapEmitNull map[string]any `json:",format:emitnull"`
SliceEmitNull []any `json:",format:emitnull"`
TimeDateOnly time.Time `json:",format:'2006-01-02'"`
TimeUnixSec time.Time `json:",format:unix"`
DurationSecs time.Duration `json:",format:sec"`
DurationNanos time.Duration `json:",format:nano"`
}{
BytesBase64: []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
BytesHex: [8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
BytesArray: []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
FloatNonFinite: math.NaN(),
MapEmitNull: nil,
SliceEmitNull: nil,
TimeDateOnly: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
TimeUnixSec: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
DurationSecs: 12*time.Hour + 34*time.Minute + 56*time.Second + 7*time.Millisecond + 8*time.Microsecond + 9*time.Nanosecond,
DurationNanos: 12*time.Hour + 34*time.Minute + 56*time.Second + 7*time.Millisecond + 8*time.Microsecond + 9*time.Nanosecond,
}
b, err := json.Marshal(&value)
if err != nil {
log.Fatal(err)
}
(*jsontext.Value)(&b).Indent()
fmt.Println(string(b))
}
{
// Base is embedded within Container.
type Base struct {
// ID is promoted into the JSON object for Container.
ID string
// Type is ignored due to presence of Container.Type.
Type string
// Time cancels out with Container.Inlined.Time.
Time time.Time
}
// Other is embedded within Container.
type Other struct{ Cost float64 }
// Container embeds Base and Other.
type Container struct {
// Base is an embedded struct and is implicitly JSON inlined.
Base
// Type takes precedence over Base.Type.
Type int
// Inlined is a named Go field, but is explicitly JSON inlined.
Inlined struct {
// User is promoted into the JSON object for Container.
User string
// Time cancels out with Base.Time.
Time string
} `json:",inline"`
// ID does not conflict with Base.ID since the JSON name is different.
ID string `json:"uuid"`
// Other is not JSON inlined since it has an explicit JSON name.
Other `json:"other"`
}
// Format an empty Container to show what fields are JSON serializable.
var input Container
b, err := json.Marshal(&input)
if err != nil {
log.Fatal(err)
}
(*jsontext.Value)(&b).Indent()
fmt.Println(string(b))
}
{
type MyStruct struct {
Foo string `json:",omitzero"`
Bar []int `json:",omitempty"`
// Both "omitzero" and "omitempty" can be specified together,
// in which case the field is omitted if either would take effect.
// This omits the Baz field either if it is a nil pointer or
// if it would have encoded as an empty JSON object.
Baz *MyStruct `json:",omitzero,omitempty"`
}
b, err := json.Marshal(struct {
Bool bool `json:",omitzero"`
Int int `json:",omitzero"`
String string `json:",omitzero"`
Time time.Time `json:",omitzero"`
Addr netip.Addr `json:",omitzero"`
Struct MyStruct `json:",omitzero"`
SliceNil []int `json:",omitzero"`
Slice []int `json:",omitzero"`
MapNil map[int]int `json:",omitzero"`
Map map[int]int `json:",omitzero"`
PointerNil *string `json:",omitzero"`
Pointer *string `json:",omitzero"`
InterfaceNil any `json:",omitzero"`
Interface any `json:",omitzero"`
}{
Bool: false,
Int: 0,
String: "",
Time: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC),
Addr: netip.Addr{},
Struct: MyStruct{Bar: []int{}, Baz: new(MyStruct)},
SliceNil: nil,
Slice: []int{},
MapNil: nil,
Map: map[int]int{},
PointerNil: nil,
Pointer: new(string),
InterfaceNil: nil,
Interface: (*string)(nil),
})
if err != nil {
log.Fatal(err)
}
(*jsontext.Value)(&b).Indent()
fmt.Println("OmitZero:", string(b))
b, err = json.Marshal(struct {
Bool bool `json:",omitempty"`
Int int `json:",omitempty"`
String string `json:",omitempty"`
Time time.Time `json:",omitempty"`
Addr netip.Addr `json:",omitempty"`
Struct MyStruct `json:",omitempty"`
Slice []int `json:",omitempty"`
Map map[int]int `json:",omitempty"`
PointerNil *string `json:",omitempty"`
Pointer *string `json:",omitempty"`
InterfaceNil any `json:",omitempty"`
Interface any `json:",omitempty"`
}{
Bool: false,
Int: 0,
String: "",
Time: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC),
Addr: netip.Addr{},
Struct: MyStruct{Bar: []int{}, Baz: new(MyStruct)},
Slice: []int{},
Map: map[int]int{},
PointerNil: nil,
Pointer: new(string),
InterfaceNil: nil,
Interface: (*string)(nil),
})
if err != nil {
log.Fatal(err)
}
(*jsontext.Value)(&b).Indent()
fmt.Println("OmitEmpty:", string(b))
}
//go:build goexperiment.jsonv2
package main
import (
"fmt"
"log"
"reflect"
"encoding/json/jsontext"
"encoding/json/v2"
)
// OrderedObject is an ordered sequence of name/value members in a JSON object.
//
// RFC 8259 defines an object as an "unordered collection".
// JSON implementations need not make "ordering of object members visible"
// to applications nor will they agree on the semantic meaning of an object if
// "the names within an object are not unique". For maximum compatibility,
// applications should avoid relying on ordering or duplicity of object names.
type OrderedObject[V any] []ObjectMember[V]
// ObjectMember is a JSON object member.
type ObjectMember[V any] struct {
Name string
Value V
}
// MarshalJSONTo encodes obj as a JSON object into enc.
func (obj *OrderedObject[V]) MarshalJSONTo(enc *jsontext.Encoder) error {
if err := enc.WriteToken(jsontext.BeginObject); err != nil {
return err
}
for i := range *obj {
member := &(*obj)[i]
if err := json.MarshalEncode(enc, &member.Name); err != nil {
return err
}
if err := json.MarshalEncode(enc, &member.Value); err != nil {
return err
}
}
if err := enc.WriteToken(jsontext.EndObject); err != nil {
return err
}
return nil
}
// UnmarshalJSONFrom decodes a JSON object from dec into obj.
func (obj *OrderedObject[V]) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
if k := dec.PeekKind(); k != '{' {
return fmt.Errorf("expected object start, but encountered %v", k)
}
if _, err := dec.ReadToken(); err != nil {
return err
}
for dec.PeekKind() != '}' {
*obj = append(*obj, ObjectMember[V]{})
member := &(*obj)[len(*obj)-1]
if err := json.UnmarshalDecode(dec, &member.Name); err != nil {
return err
}
if err := json.UnmarshalDecode(dec, &member.Value); err != nil {
return err
}
}
if _, err := dec.ReadToken(); err != nil {
return err
}
return nil
}
// The exact order of JSON object can be preserved through the use of a
// specialized type that implements [MarshalerTo] and [UnmarshalerFrom].
func main() {
// Round-trip marshal and unmarshal an ordered object.
// We expect the order and duplicity of JSON object members to be preserved.
// Specify jsontext.AllowDuplicateNames since this object contains "fizz" twice.
want := OrderedObject[string]{
{"fizz", "buzz"},
{"hello", "world"},
{"fizz", "wuzz"},
}
b, err := json.Marshal(&want, jsontext.AllowDuplicateNames(true))
if err != nil {
log.Fatal(err)
}
var got OrderedObject[string]
err = json.Unmarshal(b, &got, jsontext.AllowDuplicateNames(true))
if err != nil {
log.Fatal(err)
}
// Sanity check.
if !reflect.DeepEqual(got, want) {
log.Fatalf("roundtrip mismatch: got %v, want %v", got, want)
}
// Print the serialized JSON object.
(*jsontext.Value)(&b).Indent() // indent for readability
fmt.Println(string(b))
}
{
// Let protoMessage be "google.golang.org/protobuf/proto".Message.
type protoMessage interface{ ProtoReflect() }
// Let foopbMyMessage be a concrete implementation of proto.Message.
type foopbMyMessage struct{ protoMessage }
// Let protojson be an import of "google.golang.org/protobuf/encoding/protojson".
var protojson struct {
Marshal func(protoMessage) ([]byte, error)
Unmarshal func([]byte, protoMessage) error
}
// This value mixes both non-proto.Message types and proto.Message types.
// It should use the "json" package to handle non-proto.Message types and
// should use the "protojson" package to handle proto.Message types.
var value struct {
// GoStruct does not implement proto.Message and
// should use the default behavior of the "json" package.
GoStruct struct {
Name string
Age int
}
// ProtoMessage implements proto.Message and
// should be handled using protojson.Marshal.
ProtoMessage *foopbMyMessage
}
b, err := json.Marshal(&value,
json.WithMarshalers(json.MarshalFunc(protojson.Marshal)))
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(b, &value,
json.WithUnmarshalers(json.UnmarshalFunc(protojson.Unmarshal)))
if err != nil {
log.Fatal(err)
}
}
{
// Some global state maintained by the server.
var n int64
http.HandleFunc("/api/add", func(w http.ResponseWriter, r *http.Request) {
// Unmarshal the request from the client.
var val struct{ N int64 }
if err := json.UnmarshalRead(r.Body, &val); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
val.N = atomic.AddInt64(&n, val.N)
if err := json.MarshalWrite(w, &val); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
}
{
want := map[netip.Addr]string{
netip.MustParseAddr("192.168.0.100"): "carbonite",
netip.MustParseAddr("192.168.0.101"): "obsidian",
netip.MustParseAddr("192.168.0.102"): "diamond",
}
b, err := json.Marshal(&want, json.Deterministic(true))
if err != nil {
log.Fatal(err)
}
var got map[netip.Addr]string
err = json.Unmarshal(b, &got)
if err != nil {
log.Fatal(err)
}
if !reflect.DeepEqual(got, want) {
log.Fatalf("roundtrip mismatch: got %v, want %v", got, want)
}
(*jsontext.Value)(&b).Indent()
fmt.Println(string(b))
}
{
const input = `{
"Name": "Teal",
"Value": "#008080",
"WebSafe": false
}`
type Color struct {
Name string
Value string
// Unknown is a Go struct field that holds unknown JSON object members.
// It is marked as having this behavior with the "unknown" tag option.
//
// The type may be a jsontext.Value or map[string]T.
Unknown jsontext.Value `json:",unknown"`
}
// By default, unknown members are stored in a Go field marked as "unknown"
// or ignored if no such field exists.
var color Color
err := json.Unmarshal([]byte(input), &color)
if err != nil {
log.Fatal(err)
}
fmt.Println("Unknown members:", string(color.Unknown))
err = json.Unmarshal([]byte(input), new(Color), json.RejectUnknownMembers(true))
var serr *json.SemanticError
if errors.As(err, &serr) && serr.Err == json.ErrUnknownName {
fmt.Println("Unmarshal error:", serr.Err, strconv.Quote(serr.JSONPointer.LastToken()))
}
b, err := json.Marshal(color)
if err != nil {
log.Fatal(err)
}
fmt.Println("Output with unknown members: ", string(b))
b, err = json.Marshal(color, json.DiscardUnknownMembers(true))
if err != nil {
log.Fatal(err)
}
fmt.Println("Output without unknown members:", string(b))
}
Package-Level Type Names (total 8)
/* sort by: | */
Marshaler is implemented by types that can marshal themselves.
It is recommended that types implement [MarshalerTo] unless the implementation
is trying to avoid a hard dependency on the "jsontext" package.
It is recommended that implementations return a buffer that is safe
for the caller to retain and potentially mutate.( Marshaler) MarshalJSON() ([]byte, error)
encoding/json/jsontext.Value
log/slog.Level
*math/big.Int
time.Time
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.
MarshalerTo is implemented by types that can marshal themselves.
It is recommended that types implement MarshalerTo instead of [Marshaler]
since this is both more performant and 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 and
must not retain the pointer to [jsontext.Encoder].( MarshalerTo) MarshalJSONTo(*jsontext.Encoder) error
encoding/json.Number
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.
Options represent either a singular option or a set of options.
It can be functionally 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 singular option value:
opt := Deterministic(true)
which is analogous to creating a single entry map:
opt := Options{"Deterministic": true}
[JoinOptions] composes multiple options values to 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 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:
- [StringifyNumbers] affects marshaling and unmarshaling
- [Deterministic] affects marshaling only
- [FormatNilSliceAsNull] affects marshaling only
- [FormatNilMapAsNull] affects marshaling only
- [OmitZeroStructFields] affects marshaling only
- [MatchCaseInsensitiveNames] affects marshaling and unmarshaling
- [DiscardUnknownMembers] affects marshaling only
- [RejectUnknownMembers] affects unmarshaling only
- [WithMarshalers] affects marshaling only
- [WithUnmarshalers] affects unmarshaling only
Options that do not affect a particular operation are ignored.
SemanticError describes an error determining the meaning
of JSON data as Go data or vice-versa.
The contents of this error as produced by this package may change over time. ByteOffset indicates that an error occurred after this byte offset. Err is the underlying error. // may be nil GoType is the Go type that could not be handled. // may be nil if unknown JSONKind is the JSON kind that could not be handled. // may be zero if unknown JSONPointer indicates that an error occurred within this JSON value
as indicated using the JSON Pointer notation (see RFC 6901). JSONValue is the JSON number or string that could not be unmarshaled.
It is not populated during marshaling. // may be nil if irrelevant or unknown(*SemanticError) Error() string(*SemanticError) Unwrap() error
*SemanticError : error
Unmarshaler is implemented by types that can unmarshal themselves.
It is recommended that types implement [UnmarshalerFrom] unless the implementation
is trying to avoid a hard 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.
UnmarshalJSON must copy the JSON data if it is retained after returning.
It is recommended that UnmarshalJSON implement merge semantics when
unmarshaling into a pre-populated value.
Implementations must not retain or mutate the input []byte.( Unmarshaler) UnmarshalJSON([]byte) error
*encoding/json/jsontext.Value
*log/slog.Level
*math/big.Int
*time.Time
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 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.
Implementations must not retain the pointer to [jsontext.Decoder].( UnmarshalerFrom) UnmarshalJSONFrom(*jsontext.Decoder) error
*encoding/json.Number
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.
Package-Level Functions (total 25)
DefaultOptionsV2 is the full set of all options that define v2 semantics.
It is equivalent to all options under [Options], [encoding/json.Options],
and [encoding/json/jsontext.Options] being set to false or the zero value,
except for the options related to whitespace formatting.
Deterministic specifies that the same input value will be serialized
as the exact same output bytes. Different processes of
the same program will serialize equal values to the same bytes,
but different versions of the same program are not guaranteed
to produce the exact same sequence of bytes.
This only affects marshaling and is ignored when unmarshaling.
DiscardUnknownMembers specifies that marshaling should ignore any
JSON object members stored in Go struct fields dedicated to storing
unknown JSON object members.
This only affects marshaling and is ignored when unmarshaling.
FormatNilMapAsNull specifies that a nil Go map should marshal as a
JSON null instead of the default representation as an empty JSON object.
Map fields explicitly marked with `format:emitempty` still marshal
as an empty JSON object.
This only affects marshaling and is ignored when unmarshaling.
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).
Slice fields explicitly marked with `format:emitempty` still marshal
as an empty JSON array.
This only affects marshaling and is ignored when unmarshaling.
Type Parameters:
T: any GetOption returns the value stored in opts with the provided setter,
reporting whether the value is present.
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.
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 [SkipFunc], 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
JoinOptions coalesces the provided list of options into a single Options.
Properties set in later options override the value of previously set properties.
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 [SkipFunc], 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
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 boxing it on the heap 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 the following rules:
- If any type-specific functions in a [WithMarshalers] option match
the value type, then those functions are called to encode the value.
If all applicable functions return [SkipFunc],
then the value is encoded according to subsequent rules.
- If the value type implements [MarshalerTo],
then the MarshalJSONTo method is called to encode the value.
- If the value type implements [Marshaler],
then the MarshalJSON method is called to encode the value.
- If the value type implements [encoding.TextAppender],
then the AppendText method is called to encode the value and
subsequently encode its result as a JSON string.
- If the value type implements [encoding.TextMarshaler],
then the MarshalText method is called to encode the value and
subsequently encode its result as a JSON string.
- Otherwise, the value is encoded according to the value's type
as described in detail below.
Most Go types have a default JSON representation.
Certain types support specialized formatting according to
a format flag optionally specified in the Go struct tag
for the struct field that contains the current value
(see the “JSON Representation of Go structs” section for more details).
The representation of each type is as follows:
- A Go boolean is encoded as a JSON boolean (e.g., true or false).
It does not support any custom format flags.
- A Go string is encoded as a JSON string.
It does not support any custom format flags.
- A Go []byte or [N]byte is encoded as a JSON string containing
the binary value encoded using RFC 4648.
If the format is "base64" or unspecified, then this uses RFC 4648, section 4.
If the format is "base64url", then this uses RFC 4648, section 5.
If the format is "base32", then this uses RFC 4648, section 6.
If the format is "base32hex", then this uses RFC 4648, section 7.
If the format is "base16" or "hex", then this uses RFC 4648, section 8.
If the format is "array", then the bytes value is encoded as a JSON array
where each byte is recursively JSON-encoded as each JSON array element.
- A Go integer is encoded as a JSON number without fractions or exponents.
If [StringifyNumbers] is specified or encoding a JSON object name,
then the JSON number is encoded within a JSON string.
It does not support any custom format flags.
- A Go float is encoded as a JSON number.
If [StringifyNumbers] is specified or encoding a JSON object name,
then the JSON number is encoded within a JSON string.
If the format is "nonfinite", then NaN, +Inf, and -Inf are encoded as
the JSON strings "NaN", "Infinity", and "-Infinity", respectively.
Otherwise, the presence of non-finite numbers results in a [SemanticError].
- A Go map is encoded as a JSON object, where each Go map key and value
is recursively encoded as a name and value pair in the JSON object.
The Go map key must encode as a JSON string, otherwise this results
in a [SemanticError]. The Go map is traversed in a non-deterministic order.
For deterministic encoding, consider using the [Deterministic] option.
If the format is "emitnull", then a nil map is encoded as a JSON null.
If the format is "emitempty", then a nil map is encoded as an empty JSON object,
regardless of whether [FormatNilMapAsNull] is specified.
Otherwise by default, a nil map is encoded as an empty JSON object.
- A Go struct is encoded as a JSON object.
See the “JSON Representation of Go structs” section
in the package-level documentation for more details.
- A Go slice is encoded as a JSON array, where each Go slice element
is recursively JSON-encoded as the elements of the JSON array.
If the format is "emitnull", then a nil slice is encoded as a JSON null.
If the format is "emitempty", then a nil slice is encoded as an empty JSON array,
regardless of whether [FormatNilSliceAsNull] is specified.
Otherwise by default, a nil slice is encoded as an empty JSON array.
- A Go array is encoded as a JSON array, where each Go array element
is recursively JSON-encoded as the elements of the JSON array.
The JSON array length is always identical to the Go array length.
It does not support any custom format flags.
- A Go pointer is encoded as a JSON null if nil, otherwise it is
the recursively JSON-encoded representation of the underlying value.
Format flags are forwarded to the encoding of the underlying value.
- A Go interface is encoded as a JSON null if nil, otherwise it is
the recursively JSON-encoded representation of the underlying value.
It does not support any custom format flags.
- A Go [time.Time] is encoded as a JSON string containing the timestamp
formatted in RFC 3339 with nanosecond precision.
If the format matches one of the format constants declared
in the time package (e.g., RFC1123), then that format is used.
If the format is "unix", "unixmilli", "unixmicro", or "unixnano",
then the timestamp is encoded as a JSON number of the number of seconds
(or milliseconds, microseconds, or nanoseconds) since the Unix epoch,
which is January 1st, 1970 at 00:00:00 UTC.
Otherwise, the format is used as-is with [time.Time.Format] if non-empty.
- A Go [time.Duration] is encoded as a JSON string containing the duration
formatted according to [time.Duration.String].
If the format is "sec", "milli", "micro", or "nano",
then the duration is encoded as a JSON number of the number of seconds
(or milliseconds, microseconds, or nanoseconds) in the duration.
If the format is "units", it uses [time.Duration.String].
- All other Go types (e.g., complex numbers, channels, and functions)
have no default representation and result in a [SemanticError].
JSON cannot represent cyclic data structures and Marshal does not handle them.
Passing cyclic structures will result in an error.
MarshalEncode serializes a Go value into an [jsontext.Encoder] according to
the provided marshal options (while ignoring unmarshal, encode, or decode options).
Any marshal-relevant options already specified on the [jsontext.Encoder]
take lower precedence than the set of options provided by the caller.
Unlike [Marshal] and [MarshalWrite], encode options are ignored because
they must have already been specified on the provided [jsontext.Encoder].
See [Marshal] for details about the conversion of a Go value into JSON.
Type Parameters:
T: any 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.
The function must marshal exactly one JSON value.
The value of T must not be retained outside the function call.
It may not return [SkipFunc].
Type Parameters:
T: any 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.
The function must marshal exactly one JSON value by calling write methods
on the provided encoder. It may return [SkipFunc] such that marshaling can
move on to the next marshal function. However, no mutable method calls may
be called on the encoder if [SkipFunc] is returned.
The pointer to [jsontext.Encoder] and the value of T
must not be retained outside the function call.
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.
MatchCaseInsensitiveNames specifies that JSON object members are matched
against Go struct fields using a case-insensitive match of the name.
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.
For marshaling, this option may alter the detection of duplicate names
(assuming [jsontext.AllowDuplicateNames] is false) from inlined fields
if it matches one of the declared fields in the Go struct.
OmitZeroStructFields specifies that a Go struct should marshal in such a way
that all struct fields that are zero are omitted from the marshaled output
if the value is zero as determined by the "IsZero() bool" method if present,
otherwise based on whether the field is the zero Go value.
This is semantically equivalent to specifying the `omitzero` tag option
on every field in a Go struct.
This only affects marshaling and is ignored when unmarshaling.
RejectUnknownMembers specifies that unknown members should be rejected
when unmarshaling a JSON object, regardless of whether there is a field
to store unknown members.
This only affects unmarshaling and is ignored when marshaling.
StringifyNumbers specifies that numeric Go types should be marshaled
as a JSON string containing the equivalent JSON number value.
When unmarshaling, numeric Go types are parsed from a JSON string
containing the JSON number without any surrounding whitespace.
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.
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 boxing it on the heap if necessary) so that
these functions and methods can be consistently called.
The input is decoded into the output according the following rules:
- If any type-specific functions in a [WithUnmarshalers] option match
the value type, then those functions are called to decode the JSON
value. If all applicable functions return [SkipFunc],
then the input is decoded according to subsequent rules.
- If the value type implements [UnmarshalerFrom],
then the UnmarshalJSONFrom method is called to decode the JSON value.
- If the value type implements [Unmarshaler],
then the UnmarshalJSON method is called to decode the JSON value.
- If the value type implements [encoding.TextUnmarshaler],
then the input is decoded as a JSON string and
the UnmarshalText method is called with the decoded string value.
This fails with a [SemanticError] if the input is not a JSON string.
- Otherwise, the JSON value is decoded according to the value's type
as described in detail below.
Most Go types have a default JSON representation.
Certain types support specialized formatting according to
a format flag optionally specified in the Go struct tag
for the struct field that contains the current value
(see the “JSON Representation of Go structs” section for more details).
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:
- A Go boolean is decoded from a JSON boolean (e.g., true or false).
It does not support any custom format flags.
- A Go string is decoded from a JSON string.
It does not support any custom format flags.
- A Go []byte or [N]byte is decoded from a JSON string
containing the binary value encoded using RFC 4648.
If the format is "base64" or unspecified, then this uses RFC 4648, section 4.
If the format is "base64url", then this uses RFC 4648, section 5.
If the format is "base32", then this uses RFC 4648, section 6.
If the format is "base32hex", then this uses RFC 4648, section 7.
If the format is "base16" or "hex", then this uses RFC 4648, section 8.
If the format is "array", then the Go slice or array is decoded from a
JSON array where each JSON element is recursively decoded for each byte.
When decoding into a non-nil []byte, the slice length is reset to zero
and the decoded input is appended to it.
When decoding into a [N]byte, the input must decode to exactly N bytes,
otherwise it fails with a [SemanticError].
- A Go integer is decoded from a JSON number.
It must be decoded from a JSON string containing a JSON number
if [StringifyNumbers] is specified or decoding a JSON object name.
It fails with a [SemanticError] if the JSON number
has a fractional or exponent component.
It also fails if it overflows the representation of the Go integer type.
It does not support any custom format flags.
- A Go float is decoded from a JSON number.
It must be decoded from a JSON string containing a JSON number
if [StringifyNumbers] is specified or decoding a JSON object name.
It fails if it overflows the representation of the Go float type.
If the format is "nonfinite", then the JSON strings
"NaN", "Infinity", and "-Infinity" are decoded as NaN, +Inf, and -Inf.
Otherwise, the presence of such strings results in a [SemanticError].
- A Go map is decoded from a JSON object,
where each JSON object name and value pair is recursively decoded
as the Go map key and value. Maps are not cleared.
If the Go map is nil, then a new map is allocated to decode into.
If the decoded key matches an existing Go map entry, the entry value
is reused by decoding the JSON object value into it.
The formats "emitnull" and "emitempty" have no effect when decoding.
- A Go struct is decoded from a JSON object.
See the “JSON Representation of Go structs” section
in the package-level documentation for more details.
- A Go slice is decoded from a JSON array, where each JSON element
is recursively decoded and appended to the Go slice.
Before appending into a Go slice, a new slice is allocated if it is nil,
otherwise the slice length is reset to zero.
The formats "emitnull" and "emitempty" have no effect when decoding.
- A Go array is decoded from a JSON array, where each JSON array element
is recursively decoded as each corresponding Go array element.
Each Go array element is zeroed before decoding into it.
It fails with a [SemanticError] if the JSON array does not contain
the exact same number of elements as the Go array.
It does not support any custom format flags.
- A Go pointer is decoded based on the JSON kind and underlying Go type.
If the input is a JSON null, then this stores a nil pointer.
Otherwise, it allocates a new underlying value if the pointer is nil,
and recursively JSON decodes into the underlying value.
Format flags are forwarded to the decoding of the underlying type.
- A Go interface is decoded based on the JSON kind and underlying Go type.
If the input is a JSON null, then this stores a nil interface value.
Otherwise, a nil interface value of an empty interface type is initialized
with a zero Go bool, string, float64, map[string]any, or []any if the
input is a JSON boolean, string, number, object, or array, respectively.
If the interface value is still nil, then this fails with a [SemanticError]
since decoding could not determine an appropriate Go type to decode into.
For example, unmarshaling into a nil io.Reader fails since
there is no concrete type to populate the interface value with.
Otherwise an underlying value exists and it recursively decodes
the JSON input into it. It does not support any custom format flags.
- A Go [time.Time] is decoded from a JSON string containing the time
formatted in RFC 3339 with nanosecond precision.
If the format matches one of the format constants declared in
the time package (e.g., RFC1123), then that format is used for parsing.
If the format is "unix", "unixmilli", "unixmicro", or "unixnano",
then the timestamp is decoded from a JSON number of the number of seconds
(or milliseconds, microseconds, or nanoseconds) since the Unix epoch,
which is January 1st, 1970 at 00:00:00 UTC.
Otherwise, the format is used as-is with [time.Time.Parse] if non-empty.
- A Go [time.Duration] is decoded from a JSON string by
passing the decoded string to [time.ParseDuration].
If the format is "sec", "milli", "micro", or "nano",
then the duration is decoded from a JSON number of the number of seconds
(or milliseconds, microseconds, or nanoseconds) in the duration.
If the format is "units", it uses [time.ParseDuration].
- All other Go types (e.g., complex numbers, channels, and functions)
have no default representation and result in a [SemanticError].
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.
UnmarshalDecode deserializes a Go value from a [jsontext.Decoder] according to
the provided unmarshal options (while ignoring marshal, encode, or decode options).
Any unmarshal options already specified on the [jsontext.Decoder]
take lower precedence than the set of options provided by the caller.
Unlike [Unmarshal] and [UnmarshalRead], decode options are ignored because
they must have already been specified on the provided [jsontext.Decoder].
The input may be a stream of one or more JSON values,
where this only unmarshals the next JSON value in the stream.
The output must be a non-nil pointer.
See [Unmarshal] for details about the conversion of JSON into a Go value.
Type Parameters:
T: any 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.
The function must unmarshal exactly one JSON value by calling read methods
on the provided decoder. It may return [SkipFunc] such that unmarshaling can
move on to the next unmarshal function. However, no mutable method calls may
be called on the decoder if [SkipFunc] is returned.
The pointer to [jsontext.Decoder] and the value of T
must not be retained outside the function call.
Type Parameters:
T: any 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.
The function must unmarshal exactly one JSON value.
The input []byte must not be mutated.
The input []byte and value T must not be retained outside the function call.
It may not return [SkipFunc].
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.
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.
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.
Package-Level Variables (total 2)
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 := ...
var serr json.SemanticError
if errors.As(err, &serr) && 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.
The pages are generated with Goldsv0.7.7-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.