Involved Source Filesarshal.goarshal_any.goarshal_default.goarshal_embedded.goarshal_funcs.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.
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],
unless the Go struct has a field with an explicit `json` tag,
which signals that the type has a valid JSON representation (even if empty).
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.
[Working with JSON]: https://go.dev/doc/tutorial/json
[For example, suppose we have two micro-services.]: https://www.youtube.com/watch?v=avilmOcHKHE&t=1057serrors.gofields.gofold.gointern.gooptions.go
Code Examples
package main
import (
"fmt"
"log"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
type Pet struct {
Name string
Species string
Breed string
}
p := Pet{
Name: "Oliver",
Species: "Dog",
Breed: "Goldendoodle",
}
b, err := json.Marshal(p, jsontext.Multiline(true))
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
package main
import (
"fmt"
"log"
"maps"
"slices"
"encoding/json/jsontext"
"encoding/json/v2"
)
// IntSet is a simple set of numbers, implemented using a map.
type IntSet map[int]struct{}
// MarshalJSONTo encodes s as a JSON array into enc.
func (s *IntSet) MarshalJSONTo(enc *jsontext.Encoder) error {
if err := enc.WriteToken(jsontext.BeginArray); err != nil {
return err
}
keys := maps.Keys(*s)
deterministic, _ := json.GetOption(enc.Options(), json.Deterministic)
if deterministic {
keys = slices.Values(slices.Sorted(keys))
}
for k := range keys {
if err := json.MarshalEncode(enc, k); err != nil {
return err
}
}
if err := enc.WriteToken(jsontext.EndArray); err != nil {
return err
}
return nil
}
// UnmarshalJSONFrom decodes a JSON array from dec into s.
func (s *IntSet) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
if k := dec.PeekKind(); k != '[' {
return &json.SemanticError{JSONKind: k}
}
if _, err := dec.ReadToken(); err != nil {
return err
}
for dec.PeekKind() != ']' {
var v int
if err := json.UnmarshalDecode(dec, &v); err != nil {
return err
}
if *s == nil {
*s = IntSet{}
}
(*s)[v] = struct{}{}
}
if _, err := dec.ReadToken(); err != nil {
return err
}
return nil
}
func main() {
set := IntSet{
1: {},
2: {},
3: {},
}
b, err := json.Marshal(&set, json.Deterministic(true))
if err != nil {
log.Fatal(err)
}
// Indent output for readability.
v := jsontext.Value(b)
v.Indent()
fmt.Println(string(v))
}
package main
import (
"fmt"
"io"
"log"
"strings"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
const jsonStream = `
{"Name": "Platypus", "Order": "Monotremata"}
{"Name": "Quoll", "Order": "Dasyuromorphia"}
{"Name": "Gopher", "Order": "Rodentia"}
`
type Animal struct {
Name string
Order string
}
dec := jsontext.NewDecoder(strings.NewReader(jsonStream))
for {
var a Animal
if err := json.UnmarshalDecode(dec, &a); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
fmt.Printf("%s: %s\n", a.Name, a.Order)
}
}
package main
import (
"fmt"
"log"
"maps"
"slices"
"encoding/json/jsontext"
"encoding/json/v2"
)
// IntSet is a simple set of numbers, implemented using a map.
type IntSet map[int]struct{}
// MarshalJSONTo encodes s as a JSON array into enc.
func (s *IntSet) MarshalJSONTo(enc *jsontext.Encoder) error {
if err := enc.WriteToken(jsontext.BeginArray); err != nil {
return err
}
keys := maps.Keys(*s)
deterministic, _ := json.GetOption(enc.Options(), json.Deterministic)
if deterministic {
keys = slices.Values(slices.Sorted(keys))
}
for k := range keys {
if err := json.MarshalEncode(enc, k); err != nil {
return err
}
}
if err := enc.WriteToken(jsontext.EndArray); err != nil {
return err
}
return nil
}
// UnmarshalJSONFrom decodes a JSON array from dec into s.
func (s *IntSet) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
if k := dec.PeekKind(); k != '[' {
return &json.SemanticError{JSONKind: k}
}
if _, err := dec.ReadToken(); err != nil {
return err
}
for dec.PeekKind() != ']' {
var v int
if err := json.UnmarshalDecode(dec, &v); err != nil {
return err
}
if *s == nil {
*s = IntSet{}
}
(*s)[v] = struct{}{}
}
if _, err := dec.ReadToken(); err != nil {
return err
}
return nil
}
func main() {
s := "[1,2,3]"
var set IntSet
err := json.Unmarshal([]byte(s), &set)
if err != nil {
log.Fatal(err)
}
fmt.Println(set)
}
package main
import (
"fmt"
"log"
"os"
"strconv"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
// Response to serialize with some Go errors encountered.
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,
// Intercept every attempt to marshal an error type.
json.WithMarshalers(json.JoinMarshalers(
// Suppose we consider strconv.NumError to be a safe to serialize:
// this type-specific marshal function intercepts this type
// and encodes the error message as a JSON string.
json.MarshalToFunc(func(enc *jsontext.Encoder, err *strconv.NumError) error {
return enc.WriteToken(jsontext.String(err.Error()))
}),
// Error messages may contain sensitive information that may not
// be appropriate to serialize. For all errors not handled above,
// report some generic error message.
json.MarshalFunc(func(error) ([]byte, error) {
return []byte(`"internal server error"`), nil
}),
)),
jsontext.Multiline(true)) // expand for readability
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
package main
import (
"errors"
"fmt"
"log"
"reflect"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
// 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,
// Intercept every attempt to unmarshal into the any type.
json.WithUnmarshalers(
json.UnmarshalFromFunc(func(dec *jsontext.Decoder, val *any) error {
// If the next value to be decoded is a JSON number,
// then provide a concrete Go type to unmarshal into.
if dec.PeekKind() == '0' {
*val = jsontext.Value(nil)
}
// Return ErrUnsupported to fallback on default unmarshal behavior.
return errors.ErrUnsupported
}),
))
if err != nil {
log.Fatal(err)
}
fmt.Println(value)
// Sanity check.
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)
}
}
package main
import (
"bytes"
"errors"
"fmt"
"log"
"net/netip"
"strings"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
// 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,
// Intercept every attempt to unmarshal into the Tunnel type.
json.WithUnmarshalers(
json.UnmarshalFromFunc(func(dec *jsontext.Decoder, tunnel *Tunnel) error {
// Decoder.InputOffset reports the offset after the last token,
// but we want to record the offset before the next token.
//
// Call Decoder.PeekKind to buffer enough to reach the next token.
// Add the number of leading whitespace, commas, and colons
// to locate the start of the next token.
dec.PeekKind()
unread := dec.UnreadBuffer()
n := len(unread) - len(bytes.TrimLeft(unread, " \n\r\t,:"))
tunnel.ByteOffset = dec.InputOffset() + int64(n)
// Return ErrUnsupported to fallback on default unmarshal behavior.
return errors.ErrUnsupported
}),
))
if err != nil {
log.Fatal(err)
}
// lineColumn converts a byte offset into a one-indexed line and column.
// The offset must be within the bounds of the input.
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
}
// Verify that the configuration file is valid.
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)
}
}
}
package main
import (
"fmt"
"log"
"encoding/json/v2"
)
func main() {
// 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) // exactly 1 match found
// 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) // 8 matches found
}
package main
import (
"fmt"
"log"
"time"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
// 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.Embed.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 embedded.
Base
// Type takes precedence over Base.Type.
Type int
// Embed is a named Go field, but is explicitly JSON embedded.
Embed struct {
// User is promoted into the JSON object for Container.
User string
// Time cancels out with Base.Time.
Time string
} `json:",embed"`
// ID does not conflict with Base.ID since the JSON name is different.
ID string `json:"uuid"`
// Other is not JSON embedded 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)
}
// Indent output for readability.
v := jsontext.Value(b)
v.Indent()
fmt.Println(string(v))
}
package main
import (
"fmt"
"log"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
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 unexported field is always ignored.
unexported any
}
b, err := json.Marshal(value)
if err != nil {
log.Fatal(err)
}
// Indent output for readability.
v := jsontext.Value(b)
v.Indent()
fmt.Println(string(v))
}
package main
import (
"fmt"
"log"
"net/netip"
"time"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
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"`
}
// Demonstrate behavior of "omitzero".
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 is omitted since false is the zero value for a Go bool.
Bool: false,
// Int is omitted since 0 is the zero value for a Go int.
Int: 0,
// String is omitted since "" is the zero value for a Go string.
String: "",
// Time is omitted since time.Time.IsZero reports true.
Time: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC),
// Addr is omitted since netip.Addr{} is the zero value for a Go struct.
Addr: netip.Addr{},
// Struct is NOT omitted since it is not the zero value for a Go struct.
Struct: MyStruct{Bar: []int{}, Baz: new(MyStruct)},
// SliceNil is omitted since nil is the zero value for a Go slice.
SliceNil: nil,
// Slice is NOT omitted since []int{} is not the zero value for a Go slice.
Slice: []int{},
// MapNil is omitted since nil is the zero value for a Go map.
MapNil: nil,
// Map is NOT omitted since map[int]int{} is not the zero value for a Go map.
Map: map[int]int{},
// PointerNil is omitted since nil is the zero value for a Go pointer.
PointerNil: nil,
// Pointer is NOT omitted since new(string) is not the zero value for a Go pointer.
Pointer: new(string),
// InterfaceNil is omitted since nil is the zero value for a Go interface.
InterfaceNil: nil,
// Interface is NOT omitted since (*string)(nil) is not the zero value for a Go interface.
Interface: (*string)(nil),
})
if err != nil {
log.Fatal(err)
}
// Indent output for readability.
v := jsontext.Value(b)
v.Indent()
fmt.Println("OmitZero:", string(v)) // outputs "Struct", "Slice", "Map", "Pointer", and "Interface"
// Demonstrate behavior of "omitempty".
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 is NOT omitted since false is not an empty JSON value.
Bool: false,
// Int is NOT omitted since 0 is not a empty JSON value.
Int: 0,
// String is omitted since "" is an empty JSON string.
String: "",
// Time is NOT omitted since this encodes as a non-empty JSON string.
Time: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC),
// Addr is omitted since this encodes as an empty JSON string.
Addr: netip.Addr{},
// Struct is omitted since {} is an empty JSON object.
Struct: MyStruct{Bar: []int{}, Baz: new(MyStruct)},
// Slice is omitted since [] is an empty JSON array.
Slice: []int{},
// Map is omitted since {} is an empty JSON object.
Map: map[int]int{},
// PointerNil is omitted since null is an empty JSON value.
PointerNil: nil,
// Pointer is omitted since "" is an empty JSON string.
Pointer: new(string),
// InterfaceNil is omitted since null is an empty JSON value.
InterfaceNil: nil,
// Interface is omitted since null is an empty JSON value.
Interface: (*string)(nil),
})
if err != nil {
log.Fatal(err)
}
// Indent output for readability.
v = jsontext.Value(b)
v.Indent()
fmt.Println("OmitEmpty:", string(v)) // outputs "Bool", "Int", and "Time"
}
//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 != '{' {
// The [json] package automatically populates relevant fields
// in a [json.SemanticError] to provide additional context.
return &json.SemanticError{JSONKind: 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)
}
// Indent output for readability.
v := jsontext.Value(b)
v.Indent()
fmt.Println(string(v))
}
package main
import (
"log"
"encoding/json/v2"
)
func main() {
// 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
}
// Marshal using protojson.Marshal for proto.Message types.
b, err := json.Marshal(&value,
// Use protojson.Marshal as a type-specific marshaler.
json.WithMarshalers(json.MarshalFunc(protojson.Marshal)))
if err != nil {
log.Fatal(err)
}
// Unmarshal using protojson.Unmarshal for proto.Message types.
err = json.Unmarshal(b, &value,
// Use protojson.Unmarshal as a type-specific unmarshaler.
json.WithUnmarshalers(json.UnmarshalFunc(protojson.Unmarshal)))
if err != nil {
log.Fatal(err)
}
}
package main
import (
"net/http"
"sync/atomic"
"encoding/json/v2"
)
func main() {
// Some global state maintained by the server.
var n int64
// The "add" endpoint accepts a POST request with a JSON object
// containing a number to atomically add to the server's global counter.
// It returns the updated value of the counter.
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 {
// Inability to unmarshal the input suggests a client-side problem.
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Marshal a response from the server.
val.N = atomic.AddInt64(&n, val.N)
if err := json.MarshalWrite(w, &val); err != nil {
// Inability to marshal the output suggests a server-side problem.
// This error is not always observable by the client since
// json.MarshalWrite may have already written to the output.
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
}
package main
import (
"fmt"
"log"
"net/netip"
"reflect"
"encoding/json/jsontext"
"encoding/json/v2"
)
func main() {
// Round-trip marshal and unmarshal a hostname map where the netip.Addr type
// implements both encoding.TextMarshaler and encoding.TextUnmarshaler.
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)
}
// Sanity check.
if !reflect.DeepEqual(got, want) {
log.Fatalf("roundtrip mismatch: got %v, want %v", got, want)
}
// Indent output for readability.
v := jsontext.Value(b)
v.Indent()
fmt.Println(string(v))
}
Package-Level Type Names (total 35, in which 8 are exported)
/* sort exporteds by: | */
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.( Marshaler) MarshalJSON() ([]byte, error)
encoding/json/jsontext.Value
github.com/jackc/pgx/v5/pgproto3.AuthenticationCleartextPassword
*github.com/jackc/pgx/v5/pgproto3.AuthenticationGSS
*github.com/jackc/pgx/v5/pgproto3.AuthenticationGSSContinue
github.com/jackc/pgx/v5/pgproto3.AuthenticationMD5Password
github.com/jackc/pgx/v5/pgproto3.AuthenticationOk
github.com/jackc/pgx/v5/pgproto3.AuthenticationSASL
github.com/jackc/pgx/v5/pgproto3.AuthenticationSASLContinue
github.com/jackc/pgx/v5/pgproto3.AuthenticationSASLFinal
github.com/jackc/pgx/v5/pgproto3.BackendKeyData
github.com/jackc/pgx/v5/pgproto3.Bind
github.com/jackc/pgx/v5/pgproto3.BindComplete
github.com/jackc/pgx/v5/pgproto3.CancelRequest
github.com/jackc/pgx/v5/pgproto3.Close
github.com/jackc/pgx/v5/pgproto3.CloseComplete
github.com/jackc/pgx/v5/pgproto3.CommandComplete
github.com/jackc/pgx/v5/pgproto3.CopyBothResponse
github.com/jackc/pgx/v5/pgproto3.CopyData
github.com/jackc/pgx/v5/pgproto3.CopyDone
github.com/jackc/pgx/v5/pgproto3.CopyFail
github.com/jackc/pgx/v5/pgproto3.CopyInResponse
github.com/jackc/pgx/v5/pgproto3.CopyOutResponse
github.com/jackc/pgx/v5/pgproto3.DataRow
github.com/jackc/pgx/v5/pgproto3.Describe
github.com/jackc/pgx/v5/pgproto3.EmptyQueryResponse
github.com/jackc/pgx/v5/pgproto3.ErrorResponse
github.com/jackc/pgx/v5/pgproto3.Execute
github.com/jackc/pgx/v5/pgproto3.FieldDescription
github.com/jackc/pgx/v5/pgproto3.Flush
github.com/jackc/pgx/v5/pgproto3.FunctionCallResponse
github.com/jackc/pgx/v5/pgproto3.GSSEncRequest
*github.com/jackc/pgx/v5/pgproto3.GSSResponse
github.com/jackc/pgx/v5/pgproto3.NegotiateProtocolVersion
github.com/jackc/pgx/v5/pgproto3.NoData
github.com/jackc/pgx/v5/pgproto3.NotificationResponse
github.com/jackc/pgx/v5/pgproto3.ParameterDescription
github.com/jackc/pgx/v5/pgproto3.ParameterStatus
github.com/jackc/pgx/v5/pgproto3.Parse
github.com/jackc/pgx/v5/pgproto3.ParseComplete
github.com/jackc/pgx/v5/pgproto3.PasswordMessage
github.com/jackc/pgx/v5/pgproto3.PortalSuspended
github.com/jackc/pgx/v5/pgproto3.Query
github.com/jackc/pgx/v5/pgproto3.ReadyForQuery
github.com/jackc/pgx/v5/pgproto3.RowDescription
github.com/jackc/pgx/v5/pgproto3.SASLInitialResponse
github.com/jackc/pgx/v5/pgproto3.SASLResponse
github.com/jackc/pgx/v5/pgproto3.SSLRequest
github.com/jackc/pgx/v5/pgproto3.StartupMessage
github.com/jackc/pgx/v5/pgproto3.Sync
github.com/jackc/pgx/v5/pgproto3.Terminate
github.com/jackc/pgx/v5/pgtype.Bool
github.com/jackc/pgx/v5/pgtype.Date
github.com/jackc/pgx/v5/pgtype.Float4
github.com/jackc/pgx/v5/pgtype.Float8
github.com/jackc/pgx/v5/pgtype.Int2
github.com/jackc/pgx/v5/pgtype.Int4
github.com/jackc/pgx/v5/pgtype.Int8
github.com/jackc/pgx/v5/pgtype.Numeric
github.com/jackc/pgx/v5/pgtype.Point
github.com/jackc/pgx/v5/pgtype.Text
github.com/jackc/pgx/v5/pgtype.Timestamp
github.com/jackc/pgx/v5/pgtype.Timestamptz
github.com/jackc/pgx/v5/pgtype.Uint32
github.com/jackc/pgx/v5/pgtype.UUID
*golang.org/x/tools/go/packages.Package
*google.golang.org/grpc/attributes.Attributes
*google.golang.org/grpc/internal/serviceconfig.BalancerConfig
google.golang.org/grpc/internal/serviceconfig.Duration
log/slog.Level
*math/big.Int
time.Time
golang.org/x/tools/go/packages.loaderPackage
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 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.( 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.
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:
- [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
- [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.
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. ByteOffset indicates that an error occurred at or 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 // either "marshal" or "unmarshal"nonComparablenonComparablerequireKeyedLiteralsrequireKeyedLiterals(*SemanticError) Error() string(*SemanticError) Unwrap() error
*SemanticError : error
func makeStructFields(root reflect.Type) (fs structFields, serr *SemanticError)
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].( Unmarshaler) UnmarshalJSON([]byte) error
*encoding/json/jsontext.Value
*github.com/jackc/pgx/v5/pgproto3.AuthenticationGSS
*github.com/jackc/pgx/v5/pgproto3.AuthenticationGSSContinue
*github.com/jackc/pgx/v5/pgproto3.AuthenticationMD5Password
*github.com/jackc/pgx/v5/pgproto3.AuthenticationSASLContinue
*github.com/jackc/pgx/v5/pgproto3.AuthenticationSASLFinal
*github.com/jackc/pgx/v5/pgproto3.BackendKeyData
*github.com/jackc/pgx/v5/pgproto3.Bind
*github.com/jackc/pgx/v5/pgproto3.CancelRequest
*github.com/jackc/pgx/v5/pgproto3.Close
*github.com/jackc/pgx/v5/pgproto3.CommandComplete
*github.com/jackc/pgx/v5/pgproto3.CopyBothResponse
*github.com/jackc/pgx/v5/pgproto3.CopyData
*github.com/jackc/pgx/v5/pgproto3.CopyInResponse
*github.com/jackc/pgx/v5/pgproto3.CopyOutResponse
*github.com/jackc/pgx/v5/pgproto3.DataRow
*github.com/jackc/pgx/v5/pgproto3.Describe
*github.com/jackc/pgx/v5/pgproto3.ErrorResponse
*github.com/jackc/pgx/v5/pgproto3.FunctionCallResponse
*github.com/jackc/pgx/v5/pgproto3.GSSResponse
*github.com/jackc/pgx/v5/pgproto3.NegotiateProtocolVersion
*github.com/jackc/pgx/v5/pgproto3.ReadyForQuery
*github.com/jackc/pgx/v5/pgproto3.RowDescription
*github.com/jackc/pgx/v5/pgproto3.SASLInitialResponse
*github.com/jackc/pgx/v5/pgproto3.SASLResponse
*github.com/jackc/pgx/v5/pgtype.Bool
*github.com/jackc/pgx/v5/pgtype.Date
*github.com/jackc/pgx/v5/pgtype.Float4
*github.com/jackc/pgx/v5/pgtype.Float8
*github.com/jackc/pgx/v5/pgtype.Int2
*github.com/jackc/pgx/v5/pgtype.Int4
*github.com/jackc/pgx/v5/pgtype.Int8
*github.com/jackc/pgx/v5/pgtype.Numeric
*github.com/jackc/pgx/v5/pgtype.Point
*github.com/jackc/pgx/v5/pgtype.Text
*github.com/jackc/pgx/v5/pgtype.Timestamp
*github.com/jackc/pgx/v5/pgtype.Timestamptz
*github.com/jackc/pgx/v5/pgtype.Uint32
*github.com/jackc/pgx/v5/pgtype.UUID
*go.uber.org/zap/zapcore.TimeEncoder
*golang.org/x/tools/go/packages.Package
*google.golang.org/grpc/codes.Code
*google.golang.org/grpc/internal/serviceconfig.BalancerConfig
*google.golang.org/grpc/internal/serviceconfig.Duration
*log/slog.Level
*math/big.Int
*time.Time
golang.org/x/tools/go/packages.loaderPackage
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.( 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.
addressableValue is a reflect.Value that is guaranteed to be addressable
such that calling the Addr and Set methods do not panic.
There is no compile magic that enforces this property,
but rather the need to construct this type makes it easier to examine each
construction site to ensure that this property is upheld.Valuereflect.Value forcedAddr reports whether this value is addressable
only through the use of [newAddressableValue].
This is only used for [jsonflags.CallMethodsWithLegacySemantics]. flag holds metadata about the value.
The lowest five bits give the Kind of the value, mirroring typ.Kind().
The next set of bits are flag bits:
- flagStickyRO: obtained via unexported not embedded field, so read-only
- flagEmbedRO: obtained via unexported embedded field, so read-only
- flagIndir: val holds a pointer to the data
- flagAddr: v.CanAddr is true (implies flagIndir and ptr is non-nil)
- flagMethod: v is a method value.
If !typ.IsDirectIface(), code can assume that flagIndir is set.
The remaining 22+ bits give a method number for method values.
If flag.kind() != Func, code can assume that flagMethod is unset. Pointer-valued data or, if flagIndir is set, pointer to data.
Valid when either flagIndir is set or typ.pointers() is true. typ_ holds the type of the value represented by a Value.
Access using the typ method to avoid escape of v. Addr returns a pointer value representing the address of v.
It panics if [Value.CanAddr] returns false.
Addr is typically used to obtain a pointer to a struct field
or slice element in order to call a method that requires a
pointer receiver. Bool returns v's underlying value.
It panics if v's kind is not [Bool]. Bytes returns v's underlying value.
It panics if v's underlying value is not a slice of bytes or
an addressable array of bytes. Call calls the function v with the input arguments in.
For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]).
Call panics if v's Kind is not [Func].
It returns the output results as Values.
As in Go, each input argument must be assignable to the
type of the function's corresponding input parameter.
If v is a variadic function, Call creates the variadic slice parameter
itself, copying in the corresponding values.
It panics if the Value was obtained by accessing unexported struct fields. CallSlice calls the variadic function v with the input arguments in,
assigning the slice in[len(in)-1] to v's final variadic argument.
For example, if len(in) == 3, v.CallSlice(in) represents the Go call v(in[0], in[1], in[2]...).
CallSlice panics if v's Kind is not [Func] or if v is not variadic.
It returns the output results as Values.
As in Go, each input argument must be assignable to the
type of the function's corresponding input parameter.
It panics if the Value was obtained by accessing unexported struct fields. CanAddr reports whether the value's address can be obtained with [Value.Addr].
Such values are called addressable. A value is addressable if it is
an element of a slice, an element of an addressable array,
a field of an addressable struct, or the result of dereferencing a pointer.
If CanAddr returns false, calling [Value.Addr] will panic. CanComplex reports whether [Value.Complex] can be used without panicking. CanConvert reports whether the value v can be converted to type t.
If v.CanConvert(t) returns true then v.Convert(t) will not panic. CanFloat reports whether [Value.Float] can be used without panicking. CanInt reports whether Int can be used without panicking. CanInterface reports whether [Value.Interface] can be used without panicking. CanSet reports whether the value of v can be changed.
A [Value] can be changed only if it is addressable and was not
obtained by the use of unexported struct fields.
If CanSet returns false, calling [Value.Set] or any type-specific
setter (e.g., [Value.SetBool], [Value.SetInt]) will panic. CanUint reports whether [Value.Uint] can be used without panicking. Cap returns v's capacity.
It panics if v's Kind is not [Array], [Chan], [Slice] or pointer to [Array]. Clear clears the contents of a map or zeros the contents of a slice.
It panics if v's Kind is not [Map] or [Slice]. Close closes the channel v.
It panics if v's Kind is not [Chan] or
v is a receive-only channel. Comparable reports whether the value v is comparable.
If the type of v is an interface, this checks the dynamic type.
If this reports true then v.Interface() == x will not panic for any x,
nor will v.Equal(u) for any Value u. Complex returns v's underlying value, as a complex128.
It panics if v's Kind is not [Complex64] or [Complex128] Convert returns the value v converted to type t.
If the usual Go conversion rules do not allow conversion
of the value v to type t, or if converting v to type t panics, Convert panics. Elem returns the value that the interface v contains
or that the pointer v points to.
It panics if v's Kind is not [Interface] or [Pointer].
It returns the zero Value if v is nil. Equal reports true if v is equal to u.
For two invalid values, Equal will report true.
For an interface value, Equal will compare the value within the interface.
Otherwise, If the values have different types, Equal will report false.
Otherwise, for arrays and structs Equal will compare each element in order,
and report false if it finds non-equal elements.
During all comparisons, if values of the same type are compared,
and the type is not comparable, Equal will panic. Field returns the i'th field of the struct v.
It panics if v's Kind is not [Struct] or i is out of range. FieldByIndex returns the nested field corresponding to index.
It panics if evaluation requires stepping through a nil
pointer or a field that is not a struct. FieldByIndexErr returns the nested field corresponding to index.
It returns an error if evaluation requires stepping through a nil
pointer, but panics if it must step through a field that
is not a struct. FieldByName returns the struct field with the given name.
It returns the zero Value if no field was found.
It panics if v's Kind is not [Struct]. FieldByNameFunc returns the struct field with a name
that satisfies the match function.
It panics if v's Kind is not [Struct].
It returns the zero Value if no field was found. Fields returns an iterator over each [StructField] of v along with its [Value].
The sequence is equivalent to calling [Value.Field] successively
for each index i in the range [0, NumField()).
It panics if v's Kind is not Struct. Float returns v's underlying value, as a float64.
It panics if v's Kind is not [Float32] or [Float64] Grow increases the slice's capacity, if necessary, to guarantee space for
another n elements. After Grow(n), at least n elements can be appended
to the slice without another allocation.
It panics if v's Kind is not a [Slice], or if n is negative or too large to
allocate the memory, or if [Value.CanSet] returns false. Index returns v's i'th element.
It panics if v's Kind is not [Array], [Slice], or [String] or i is out of range. Int returns v's underlying value, as an int64.
It panics if v's Kind is not [Int], [Int8], [Int16], [Int32], or [Int64]. Interface returns v's current value as an interface{}.
It is equivalent to:
var i interface{} = (v's underlying value)
It panics if the Value was obtained by accessing
unexported struct fields. InterfaceData returns a pair of unspecified uintptr values.
It panics if v's Kind is not Interface.
In earlier versions of Go, this function returned the interface's
value as a uintptr pair. As of Go 1.4, the implementation of
interface values precludes any defined use of InterfaceData.
Deprecated: The memory representation of interface values is not
compatible with InterfaceData. IsNil reports whether its argument v is nil. The argument must be
a chan, func, interface, map, pointer, or slice value; if it is
not, IsNil panics. Note that IsNil is not always equivalent to a
regular comparison with nil in Go. For example, if v was created
by calling [ValueOf] with an uninitialized interface variable i,
i==nil will be true but v.IsNil will panic as v will be the zero
Value. IsValid reports whether v represents a value.
It returns false if v is the zero Value.
If [Value.IsValid] returns false, all other methods except String panic.
Most functions and methods never return an invalid Value.
If one does, its documentation states the conditions explicitly. IsZero reports whether v is the zero value for its type.
It panics if the argument is invalid. Kind returns v's Kind.
If v is the zero Value ([Value.IsValid] returns false), Kind returns Invalid. Len returns v's length.
It panics if v's Kind is not [Array], [Chan], [Map], [Slice], [String], or pointer to [Array]. MapIndex returns the value associated with key in the map v.
It panics if v's Kind is not [Map].
It returns the zero Value if key is not found in the map or if v represents a nil map.
As in Go, the key's value must be assignable to the map's key type. MapKeys returns a slice containing all the keys present in the map,
in unspecified order.
It panics if v's Kind is not [Map].
It returns an empty slice if v represents a nil map. MapRange returns a range iterator for a map.
It panics if v's Kind is not [Map].
Call [MapIter.Next] to advance the iterator, and [MapIter.Key]/[MapIter.Value] to access each entry.
[MapIter.Next] returns false when the iterator is exhausted.
MapRange follows the same iteration semantics as a range statement.
Example:
iter := reflect.ValueOf(m).MapRange()
for iter.Next() {
k := iter.Key()
v := iter.Value()
...
} Method returns a function value corresponding to v's i'th method.
The arguments to a Call on the returned function should not include
a receiver; the returned function will always use v as the receiver.
Method panics if i is out of range or if v is a nil interface value.
Calling this method will force the linker to retain all exported methods in all packages.
This may make the executable binary larger but will not affect execution time. MethodByName returns a function value corresponding to the method
of v with the given name.
The arguments to a Call on the returned function should not include
a receiver; the returned function will always use v as the receiver.
It returns the zero Value if no method was found.
Calling this method will cause the linker to retain all methods with this name in all packages.
If the linker can't determine the name, it will retain all exported methods.
This may make the executable binary larger but will not affect execution time. Methods returns an iterator over each [Method] of v along with the corresponding
method [Value]; this is a function with v bound as the receiver. As such, the
receiver shouldn't be included in the arguments to [Value.Call].
The sequence is equivalent to calling [Value.Method] successively
for each index i in the range [0, NumMethod()).
Methods panics if v is a nil interface value.
Calling this method will force the linker to retain all exported methods in all packages.
This may make the executable binary larger but will not affect execution time. NumField returns the number of fields in the struct v.
It panics if v's Kind is not [Struct]. NumMethod returns the number of methods in the value's method set.
For a non-interface type, it returns the number of exported methods.
For an interface type, it returns the number of exported and unexported methods. OverflowComplex reports whether the complex128 x cannot be represented by v's type.
It panics if v's Kind is not [Complex64] or [Complex128]. OverflowFloat reports whether the float64 x cannot be represented by v's type.
It panics if v's Kind is not [Float32] or [Float64]. OverflowInt reports whether the int64 x cannot be represented by v's type.
It panics if v's Kind is not [Int], [Int8], [Int16], [Int32], or [Int64]. OverflowUint reports whether the uint64 x cannot be represented by v's type.
It panics if v's Kind is not [Uint], [Uintptr], [Uint8], [Uint16], [Uint32], or [Uint64]. Pointer returns v's value as a uintptr.
It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], [String], or [UnsafePointer].
If v's Kind is [Func], the returned pointer is an underlying
code pointer, but not necessarily enough to identify a
single function uniquely. In particular, functions with equal
code pointers may not have identical behaviors when called.
The only guarantee is that the result is zero if and only if
v is a nil func Value.
If v's Kind is [Slice], the returned pointer is to the first
element of the slice. If the slice is nil the returned value
is 0. If the slice is empty but non-nil the return value is non-zero.
If v's Kind is [String], the returned pointer is to the first
element of the underlying bytes of string.
It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result. Recv receives and returns a value from the channel v.
It panics if v's Kind is not [Chan].
The receive blocks until a value is ready.
The boolean value ok is true if the value x corresponds to a send
on the channel, false if it is a zero value received because the channel is closed. Send sends x on the channel v.
It panics if v's kind is not [Chan] or if x's type is not the same type as v's element type.
As in Go, x's value must be assignable to the channel's element type. Seq returns an iter.Seq[Value] that loops over the elements of v.
If v's kind is [Func], it must be a function that has no results and
that takes a single argument of type func(T) bool for some type T.
If v's kind is [Pointer], the pointer element type must have kind [Array].
Otherwise v's kind must be [Int], [Int8], [Int16], [Int32], [Int64],
[Uint], [Uint8], [Uint16], [Uint32], [Uint64], [Uintptr],
[Array], [Chan], [Map], [Slice], or [String]. Seq2 returns an iter.Seq2[Value, Value] that loops over the elements of v.
If v's kind is [Func], it must be a function that has no results and
that takes a single argument of type func(K, V) bool for some type K, V.
If v's kind is [Pointer], the pointer element type must have kind [Array].
Otherwise v's kind must be [Array], [Map], [Slice], or [String]. Set assigns x to the value v.
It panics if [Value.CanSet] returns false.
As in Go, x's value must be assignable to v's type and
must not be derived from an unexported field. SetBool sets v's underlying value.
It panics if v's Kind is not [Bool] or if [Value.CanSet] returns false. SetBytes sets v's underlying value.
It panics if v's underlying value is not a slice of bytes
or if [Value.CanSet] returns false. SetCap sets v's capacity to n.
It panics if v's Kind is not [Slice], or if n is smaller than the length or
greater than the capacity of the slice,
or if [Value.CanSet] returns false. SetComplex sets v's underlying value to x.
It panics if v's Kind is not [Complex64] or [Complex128],
or if [Value.CanSet] returns false. SetFloat sets v's underlying value to x.
It panics if v's Kind is not [Float32] or [Float64],
or if [Value.CanSet] returns false. SetInt sets v's underlying value to x.
It panics if v's Kind is not [Int], [Int8], [Int16], [Int32], or [Int64],
or if [Value.CanSet] returns false. SetIterKey assigns to v the key of iter's current map entry.
It is equivalent to v.Set(iter.Key()), but it avoids allocating a new Value.
As in Go, the key must be assignable to v's type and
must not be derived from an unexported field.
It panics if [Value.CanSet] returns false. SetIterValue assigns to v the value of iter's current map entry.
It is equivalent to v.Set(iter.Value()), but it avoids allocating a new Value.
As in Go, the value must be assignable to v's type and
must not be derived from an unexported field.
It panics if [Value.CanSet] returns false. SetLen sets v's length to n.
It panics if v's Kind is not [Slice], or if n is negative or
greater than the capacity of the slice,
or if [Value.CanSet] returns false. SetMapIndex sets the element associated with key in the map v to elem.
It panics if v's Kind is not [Map].
If elem is the zero Value, SetMapIndex deletes the key from the map.
Otherwise if v holds a nil map, SetMapIndex will panic.
As in Go, key's elem must be assignable to the map's key type,
and elem's value must be assignable to the map's elem type. SetPointer sets the [unsafe.Pointer] value v to x.
It panics if v's Kind is not [UnsafePointer]
or if [Value.CanSet] returns false. SetString sets v's underlying value to x.
It panics if v's Kind is not [String] or if [Value.CanSet] returns false. SetUint sets v's underlying value to x.
It panics if v's Kind is not [Uint], [Uintptr], [Uint8], [Uint16], [Uint32], or [Uint64],
or if [Value.CanSet] returns false. SetZero sets v to be the zero value of v's type.
It panics if [Value.CanSet] returns false. Slice returns v[i:j].
It panics if v's Kind is not [Array], [Slice] or [String], or if v is an unaddressable array,
or if the indexes are out of bounds. Slice3 is the 3-index form of the slice operation: it returns v[i:j:k].
It panics if v's Kind is not [Array] or [Slice], or if v is an unaddressable array,
or if the indexes are out of bounds. String returns the string v's underlying value, as a string.
String is a special case because of Go's String method convention.
Unlike the other getters, it does not panic if v's Kind is not [String].
Instead, it returns a string of the form "<T value>" where T is v's type.
The fmt package treats Values specially. It does not call their String
method implicitly but instead prints the concrete values they hold. TryRecv attempts to receive a value from the channel v but will not block.
It panics if v's Kind is not [Chan].
If the receive delivers a value, x is the transferred value and ok is true.
If the receive cannot finish without blocking, x is the zero Value and ok is false.
If the channel is closed, x is the zero value for the channel's element type and ok is false. TrySend attempts to send x on the channel v but will not block.
It panics if v's Kind is not [Chan].
It reports whether the value was sent.
As in Go, x's value must be assignable to the channel's element type. Type returns v's type. Uint returns v's underlying value, as a uint64.
It panics if v's Kind is not [Uint], [Uintptr], [Uint8], [Uint16], [Uint32], or [Uint64]. UnsafeAddr returns a pointer to v's data, as a uintptr.
It panics if v is not addressable.
It's preferred to use uintptr(Value.Addr().UnsafePointer()) to get the equivalent result. UnsafePointer returns v's value as a [unsafe.Pointer].
It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], [String] or [UnsafePointer].
If v's Kind is [Func], the returned pointer is an underlying
code pointer, but not necessarily enough to identify a
single function uniquely. The only guarantee is that the
result is zero if and only if v is a nil func Value.
If v's Kind is [Slice], the returned pointer is to the first
element of the slice. If the slice is nil the returned value
is nil. If the slice is empty but non-nil the return value is non-nil.
If v's Kind is [String], the returned pointer is to the first
element of the underlying bytes of string.( addressableValue) abiType() *abi.Type( addressableValue) abiTypeSlow() *abi.Type assignTo returns a value v that can be assigned directly to dst.
It panics if v is not assignable to dst.
For a conversion to an interface type, target, if not nil,
is a suggested scratch space to use.
target must be initialized memory (or nil).( addressableValue) bytesSlow() []byte( addressableValue) call(op string, in []reflect.Value) []reflect.Value( addressableValue) capNonSlice() int castTo casts va to the specified type.
If the type is an interface, then the underlying type will always
be a non-nil pointer to a concrete type.
Requirement: castableTo(va.Type(), to) must hold. extendSlice extends a slice by n elements.
Unlike Value.grow, which modifies the slice in place and
does not change the length of the slice in place,
extendSlice returns a new slice value with the length
incremented by the number of specified elements.( addressableValue) fieldByIndex(index []int, mayAlloc bool) addressableValue grow is identical to Grow but does not check for assignability.( addressableValue) indirect(mayAlloc bool) addressableValue( addressableValue) kind() reflect.Kind( addressableValue) lenNonSlice() int mustBe panics if f's kind is not expected.
Making this a method on flag instead of on Value
(and embedding flag in Value) means that we can write
the very clear v.mustBe(Bool) and have it compile into
v.flag.mustBe(Bool), which will only bother to copy the
single important word for the receiver. mustBeAssignable panics if f records that the value is not assignable,
which is to say that either it was obtained using an unexported field
or it is not addressable.( addressableValue) mustBeAssignableSlow() mustBeExported panics if f records that the value was obtained using
an unexported field.( addressableValue) mustBeExportedSlow()( addressableValue) panicNotBool() Force slow panicking path not inlined, so it won't add to the
inlining budget of the caller.
TODO: undo when the inliner is no longer bottom-up only. pointer returns the underlying pointer represented by v.
v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
if v.Kind() == Pointer, the base type must not be not-in-heap. internal recv, possibly non-blocking (nb).
v is known to be a channel.( addressableValue) ro() reflect.flag runes returns v's underlying value.
It panics if v's underlying value is not a slice of runes (int32s). internal send, possibly non-blocking.
v is known to be a channel. setRunes sets v's underlying value.
It panics if v's underlying value is not a slice of runes (int32s)
or if [Value.CanSet] returns false.( addressableValue) stringNonString() string typ returns the *abi.Type stored in the Value. This method is fast,
but it doesn't always return the correct type for the Value.
See abiType and Type, which do return the correct type.( addressableValue) typeSlow() reflect.Type
addressableValue : database/sql/driver.Validator
addressableValue : expvar.Var
addressableValue : fmt.Stringer
addressableValue : isZeroer
addressableValue : context.stringer
addressableValue : runtime.stringer
func newAddressableValue(t reflect.Type) addressableValue
func isLegacyEmpty(v addressableValue) bool
func marshalEmbeddedFallbackAll(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct, f *structField, insertUnquotedName func([]byte) bool) error
func unmarshalEmbeddedFallbackNext(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct, f *structField, quotedName, unquotedName []byte) error
base records the representation where:
- 0 uses time.Duration.String
- 1e0, 1e3, 1e6, or 1e9 use a decimal encoding of the duration as
nanoseconds, microseconds, milliseconds, or seconds.
- 8601 uses ISO 8601tdtime.Duration(*durationArshaler) appendMarshal(b []byte) ([]byte, error)(*durationArshaler) initFormat(format string) (ok bool)(*durationArshaler) isNumeric() bool(*durationArshaler) unmarshal(b []byte) (err error)
All marshal and unmarshal behavior is implemented using these signatures.
The *jsonopts.Struct argument is guaranteed to be identical to or at least
a strict super-set of the options in Encoder.Struct or Decoder.Struct.
It is identical for Marshal, Unmarshal, MarshalWrite, and UnmarshalRead.
It is a super-set for MarshalEncode and UnmarshalDecode.
These option types are declared here instead of "jsonopts"
to avoid a dependency on "reflect" from "jsonopts".(*marshalersOption) JSONOptions(internal.NotForPublicUse)
*marshalersOption : encoding/json/internal/jsonopts.Options
nonComparable can be embedded in a struct to prevent comparability.
requireKeyedLiterals can be embedded in a struct to require keyed literals.
base records the representation where:
- 0 uses RFC 3339 encoding of the timestamp
- 1e0, 1e3, 1e6, or 1e9 use a decimal encoding of the timestamp as
seconds, milliseconds, microseconds, or nanoseconds since Unix epoch.
- math.MaxUint uses time.Time.Format to encode the timestamp // time format passed to time.ParselooseRFC3339booltttime.Time(*timeArshaler) appendMarshal(b []byte) ([]byte, error)(*timeArshaler) hasCustomFormat() bool(*timeArshaler) initFormat(format string) bool(*timeArshaler) isNumeric() bool(*timeArshaler) unmarshal(b []byte) (err error)
Type Parameters:
Coder: any // map[reflect.Type]arshalerfncVals[]typedArshaler[Coder] fromAny reports whether any of Go types used to represent arbitrary JSON
(i.e., any, bool, string, float64, map[string]any, or []any) matches
any of the provided type-specific arshalers.
This bit of information is needed in arshal_default.go to determine
whether to use the specialized logic in arshal_any.go to handle
the any interface type. The logic in arshal_any.go does not support
type-specific arshal functions, so we must avoid using that logic
if this is true.nonComparablenonComparable(*typedArshalers[Coder]) lookup(fnc func(*Coder, addressableValue, *jsonopts.Struct) error, t reflect.Type) (func(*Coder, addressableValue, *jsonopts.Struct) error, bool)
func newTypedArshalers[Coder](as ...*typedArshalers[Coder]) *typedArshalers[Coder]
func newTypedArshalers[Coder](as ...*typedArshalers[Coder]) *typedArshalers[Coder]
uintSet is a set of unsigned integers.
It is optimized for most integers being close to zero.hi[]uintSet64louintSet64 has reports whether i is in the set. insert inserts i into the set and reports whether it was the first insertion.
All marshal and unmarshal behavior is implemented using these signatures.
The *jsonopts.Struct argument is guaranteed to be identical to or at least
a strict super-set of the options in Encoder.Struct or Decoder.Struct.
It is identical for Marshal, Unmarshal, MarshalWrite, and UnmarshalRead.
It is a super-set for MarshalEncode and UnmarshalDecode.
These option types are declared here instead of "jsonopts"
to avoid a dependency on "reflect" from "jsonopts".(*unmarshalersOption) JSONOptions(internal.NotForPublicUse)
*unmarshalersOption : encoding/json/internal/jsonopts.Options
Package-Level Functions (total 113, in which 24 are exported)
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.
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.
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.
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.
Type Parameters:
T: any 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.
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
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 [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
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:
- 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 [errors.ErrUnsupported],
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 method returns [errors.ErrUnsupported],
then the input is encoded according to subsequent rules.
- 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 as follows:
- A Go boolean is encoded as a JSON boolean (e.g., true or false).
- A Go string is encoded as a JSON string.
- A Go []byte or [N]byte is encoded as a JSON string containing
a binary value using Base 64 Encoding per RFC 4648, section 4.
- 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.
- 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.
Encoding a NaN or ±Inf 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.
By default, a nil map is encoded as an empty JSON object,
unless the [FormatNilMapAsNull] option is specified.
- 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.
By default, a nil slice is encoded as an empty JSON array,
unless the [FormatNilSliceAsNull] option is specified.
- 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.
- A Go pointer is encoded as a JSON null if nil, otherwise it is
the recursively JSON-encoded representation 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.
- A Go [time.Time] is encoded as a JSON string containing the timestamp
formatted in RFC 3339 with nanosecond precision.
- A Go [time.Duration] currently has no default representation and
results in a [SemanticError], unless the [encoding/json.FormatDurationAsNano]
option is specified, in which case it is encoded as a JSON number
without fractions or exponents, representing the duration in nanoseconds.
- 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.
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.
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.
Implementations must follow the requirements of [Marshaler].
Implementations must not retain the value of T.
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.
Implementations must follow the requirements of [MarshalerTo].
Implementations must not retain the pointer to [jsontext.Encoder] or the
value of T.
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.
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.
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.
RejectUnknownMembers specifies that unknown members should be rejected
when unmarshaling a JSON object.
This only affects unmarshaling and is ignored when marshaling.
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.
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:
- 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 [errors.ErrUnsupported],
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 method returns [errors.ErrUnsupported],
then the input is decoded according to subsequent rules.
- 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.
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).
- A Go string is decoded from a JSON string.
- A Go []byte or [N]byte is decoded from a JSON string containing
a binary value using Base 64 Encoding per RFC 4648, section 4.
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.
- 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.
Since JSON lacks a native representation for a NaN or ±Inf,
such values cannot be the result of decoding.
- 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.
- 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.
- 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.
- 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.
- 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.
- A Go [time.Time] is decoded from a JSON string containing the time
formatted in RFC 3339 with nanosecond precision.
- A Go [time.Duration] currently has no default representation and
results in a [SemanticError], unless the [encoding/json.FormatDurationAsNano]
option is specified, in which case it is decoded as a JSON number
without fractions or exponents, representing the duration in nanoseconds.
- 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 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.
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.
Implementations must follow the requirements of [UnmarshalerFrom].
Implementations must not retain the pointer to [jsontext.Decoder] or the
value of T.
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.
Implementations must follow the requirements of [Unmarshaler].
Implementations must not retain the value of T.
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.
appendDurationBase10 appends d formatted as a decimal fractional number,
where pow10 is a power-of-10 used to scale down the number.
appendDurationISO8601 appends an ISO 8601 duration with a restricted grammar,
where leading and trailing zeroes and zero-value designators are omitted.
It only uses hour, minute, and second designators since ISO 8601 defines
those as being "accurate", while year, month, week, and day are "nominal".
appendFracBase10 appends the fraction of n/max10,
where max10 is a power-of-10 that is larger than n.
appendPaddedBase10 appends a zero-padded encoding of n,
where max10 is a power-of-10 that is larger than n.
appendTimeUnix appends t formatted as a decimal fractional number,
where pow10 is a power-of-10 used to scale up the number.
assertCastableTo asserts that "to" is a valid type to be casted to.
These are the Go types that type-specific arshalers may operate upon.
Let AllTypes be the universal set of all possible Go types.
This function generally asserts that:
len([from for from in AllTypes if castableTo(from, to)]) > 0
otherwise it panics.
As a special-case if marshal is false, then we forbid any non-pointer or
non-interface type since it is almost always a bug trying to unmarshal
into something where the end-user caller did not pass in an addressable value
since they will not observe the mutations.
boolsCompare compares x and y, ordering false before true.
bytesCutByte is similar to bytes.Cut(b, []byte{c}),
except c may optionally be included as part of the suffix.
castableTo checks whether values of type "from" can be casted to type "to".
Nil pointer or interface "from" values are never considered castable.
This function must be kept in sync with addressableValue.castTo.
castableToFromAny reports whether "to" can be casted to from any
of the dynamic types used to represent arbitrary JSON.
collapseSemanticErrors collapses double SemanticErrors at the outer levels
into a single SemanticError by preserving the inner error,
but prepending the ByteOffset and JSONPointer with the outer error.
For example:
collapseSemanticErrors(&SemanticError{
ByteOffset: len64(`[0,{"alpha":[0,1,`),
JSONPointer: "/1/alpha/2",
GoType: reflect.TypeFor[outerType](),
Err: &SemanticError{
ByteOffset: len64(`{"foo":"bar","fizz":[0,`),
JSONPointer: "/fizz/1",
GoType: reflect.TypeFor[innerType](),
Err: ...,
},
})
results in:
&SemanticError{
ByteOffset: len64(`[0,{"alpha":[0,1,`) + len64(`{"foo":"bar","fizz":[0,`),
JSONPointer: "/1/alpha/2" + "/fizz/1",
GoType: reflect.TypeFor[innerType](),
Err: ...,
}
This is used to annotate errors returned by user-provided
v1 MarshalJSON or UnmarshalJSON methods with precise position information
if they themselves happened to return a SemanticError.
Since MarshalJSON and UnmarshalJSON are not operating on the root JSON value,
their positioning must be relative to the nested JSON value
returned by UnmarshalJSON or passed to MarshalJSON.
Therefore, we can construct an absolute position by concatenating
the outer with the inner positions.
Note that we do not use collapseSemanticErrors with user-provided functions
that take in an [jsontext.Encoder] or [jsontext.Decoder] since they contain
methods to report position relative to the root JSON value.
We assume user-constructed errors are correctly precise about position.
consumeSign consumes an optional leading negative or positive sign.
consumeTagOption consumes the next option,
which is either a Go identifier or a single-quoted string.
If the next option is invalid, it returns all of in until the next comma,
and reports an error.
foldName returns a folded string such that foldName(x) == foldName(y)
is similar to strings.EqualFold(x, y), but ignores underscore and dashes.
This allows foldName to match common naming conventions.
foldRune is a variation on unicode.SimpleFold that returns the same rune
for all runes in the same fold set.
Invariant:
foldRune(x) == foldRune(y) ⇔ strings.EqualFold(string(x), string(y))
getStrings returns a non-nil pointer to a slice with length n.
hash64 returns the hash of two uint32s as a single uint32.
implements is like t.Implements(ifaceType) but checks whether
either t or reflect.PointerTo(t) implements the interface.
It also reports whether the value needs to be addressed
in order to satisfy the interface.
implementsAny is like t.Implements(ifaceType) for a list of interfaces,
but checks whether either t or reflect.PointerTo(t) implements the interface.
indirectType unwraps one level of pointer indirection
similar to how Go only allows embedding either T or *T,
but not **T or P (which is a named pointer).
Inject support into "jsonopts" to handle these types.
isAnyType reports whether t is equivalent to the any interface type.
isFatalError reports whether this error must terminate arshaling.
All errors are considered fatal unless operating under
[jsonflags.ReportErrorsWithLegacySemantics] in which case only
syntactic errors and I/O errors are considered fatal.
isLegacyEmpty reports whether a value is empty according to the v1 definition.
makeString returns the string form of b.
It returns a pre-allocated string from c if present, otherwise
it allocates a new string, inserts it into the cache, and returns it.
mapKeyWithUniqueRepresentation reports whether all possible values of k
marshal to a different JSON value, and whether all possible JSON values
that can unmarshal into k unmarshal to different Go values.
In other words, the representation must be a bijection.
marshalArrayAny marshals a Go []any as a JSON array
(or as a JSON null if nil and [jsonflags.FormatNilSliceAsNull]).
marshalEmbeddedFallbackAll marshals all the members in an embedded fallback.
newInvalidFormatError constructs a SemanticError because
the current type t cannot handle the provided options format.
This function must be called before producing or consuming the next value.
If [jsonflags.ReportErrorsWithLegacySemantics] is specified,
then this automatically skips the next value when unmarshaling
to ensure that the value is fully consumed.
newMarshalErrorBefore wraps err in a SemanticError assuming that e
is positioned right before the next token or value, which causes an error.
newSemanticErrorWithPosition wraps err in a SemanticError assuming that
the error occurred at the provided depth, and length.
If err is already a SemanticError, then position information is only
injected if it is currently unpopulated.
If the position is unpopulated, it is ambiguous where the error occurred
in the user code, whether it was before or after the current position.
For the byte offset, we assume that the error occurred before the last read
token or value when decoding, or before the next value when encoding.
For the JSON pointer, we point to the parent object or array unless
we can be certain that it happened with an object member.
This is used to annotate errors returned by user-provided
v2 MarshalJSON or UnmarshalJSON methods or functions.
newUnmarshalErrorAfter wraps err in a SemanticError assuming that d
is positioned right after the previous token or value, which caused an error.
newUnmarshalErrorAfterWithSkipping is like [newUnmarshalErrorAfter],
but automatically skips the remainder of the current value if
[jsonflags.ReportErrorsWithLegacySemantics] is specified.
newUnmarshalErrorAfterWithValue wraps err in a SemanticError assuming that d
is positioned right after the previous token or value, which caused an error.
It also stores a copy of the last JSON value if it is a string or number.
newUnmarshalErrorBefore wraps err in a SemanticError assuming that d
is positioned right before the next token or value, which causes an error.
It does not record the next JSON kind as this error is used to indicate
the receiving Go value is invalid to unmarshal into (and not a JSON error).
However, if [jsonflags.ReportErrorsWithLegacySemantics] is specified,
then it does record the next JSON kind for historical reporting reasons.
newUnmarshalErrorBeforeWithSkipping is like [newUnmarshalErrorBefore],
but automatically skips the next value if
[jsonflags.ReportErrorsWithLegacySemantics] is specified.
parseDec2 parses b as an unsigned, base-10, 2-digit number.
The result is undefined if digits are not base-10.
parseDurationBase10 parses d from a decimal fractional number,
where pow10 is a power-of-10 used to scale up the number.
parseDurationISO8601 parses a duration according to ISO 8601-1:2019,
section 5.5.2.2 and 5.5.2.3 with the following restrictions or extensions:
- A leading minus sign is permitted for negative duration according
to ISO 8601-2:2019, section 4.4.1.9. We do not permit negative values
for each "time scale component", which is permitted by section 4.4.1.1,
but rarely supported by parsers.
- A leading plus sign is permitted (and ignored).
This is not required by ISO 8601, but not forbidden either.
There is some precedent for this as it is supported by the principle of
duration arithmetic as specified in ISO 8601-2-2019, section 14.1.
Of note, the JavaScript grammar for ISO 8601 permits a leading plus sign.
- A fractional value is only permitted for accurate units
(i.e., hour, minute, and seconds) in the last time component,
which is permissible by ISO 8601-1:2019, section 5.5.2.3.
- Both periods ('.') and commas (',') are supported as the separator
between the integer part and fraction part of a number,
as specified in ISO 8601-1:2019, section 3.2.6.
While ISO 8601 recommends comma as the default separator,
most formatters use a period.
- Leading zeros are ignored. This is not required by ISO 8601,
but also not forbidden by the standard. Many parsers support this.
- Lowercase designators are supported. This is not required by ISO 8601,
but also not forbidden by the standard. Many parsers support this.
If the nominal units of year, month, week, or day are present,
this produces a best-effort value and also reports [errInaccurateDateUnits].
The accepted grammar is identical to JavaScript's Duration:
https://tc39.es/proposal-temporal/#prod-Duration
We follow JavaScript's grammar as JSON itself is derived from JavaScript.
The Temporal.Duration.toJSON method is guaranteed to produce an output
that can be parsed by this function so long as arithmetic in JavaScript
does not use a largestUnit value higher than "hours" (which is the default).
Even if it does, this will do a best-effort parsing with inaccurate units,
but report [errInaccurateDateUnits].
parseFieldOptions parses the `json` tag in a Go struct field as
a structured set of options configuring parameters such as
the JSON member name and other features.
parseFracBase10 parses the fraction of n/max10,
where max10 is a power-of-10 that is larger than n.
parsePaddedBase10 parses b as the zero-padded encoding of n,
where max10 is a power-of-10 that is larger than n.
Truncated suffix is treated as implicit zeros.
Extended suffix is ignored, but verified to contain only digits.
parseTimeUnix parses t formatted as a decimal fractional number,
where pow10 is a power-of-10 used to scale down the number.
unmarshalEmbeddedFallbackNext unmarshals only the next member in an embedded fallback.
unmarshalObjectAny unmarshals a JSON object as a Go map[string]any.
It panics if not decoding a JSON object.
unmarshalValueAny unmarshals a JSON value as a Go any.
This assumes that there are no special formatting directives
for any possible nested value.
Duplicate names must be rejected since this does not implement merging.
visitPointer visits pointer p of type t, reporting an error if seen before.
If successfully visited, then the caller must eventually call leave.
Package-Level Variables (total 56, in which 1 is exported)
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.
Interfaces for custom serialization.
Interfaces for custom serialization.
Interfaces for custom serialization.
Most natural Go types that correspond with each JSON type.
Once a JSON object has begun processing without duplicate name verification,
it does not track the history of names that have been seen so far.
Reject changing the setting for the current JSON object namespace,
otherwise we would be operating with inconsistent state.
Note that you can change the setting before processing the start
of a different JSON object.
TODO: We could loosen this restriction in certain conditions.
If we are already checking for duplicate names,
we can momentarily disable it for the next JSON object member name.
However, if we are already NOT checking for duplicate names,
we cannot momentarily enable it for the next JSON object member name
since we already lack prior history of JSON object names.
The presence of invalid UTF-8 has an interesting intersection
with checking for duplicate names. Due to the semantic of mangling
invalid UTF-8 as the Unicode replacement character,
two string keys in a Go map (both with invalid UTF-8)
may encode as the same JSON string. Thus, we forbid changing of
invalid UTF-8 checks in the current JSON object namespace.
TODO(https://go.dev/issue/79559): Changing whitespace currently
leads to strange effects and will need more careful adjustment.
For now, we just report an error.
errorModalVerb is a modal verb like "cannot" or "unable to".
Once per process, Hyrum-proof the error message by deliberately
switching between equivalent renderings of the same error message.
The randomization is tied to the Hyrum-proofing already applied
on map iteration in Go.
daysPerYear is the exact average number of days in a year according to
the Gregorian calendar, which has an extra day each year that is
a multiple of 4, unless it is evenly divisible by 100 but not by 400.
This does not take into account leap seconds, which are not deterministic.
optimizeCommon specifies whether to use optimizations targeted for certain
common patterns, rather than using the slower, but more general logic.
All tests should pass regardless of whether this is true or not.