Source file src/encoding/json/v2/arshal.go
1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build goexperiment.jsonv2 6 7 package json 8 9 import ( 10 "bytes" 11 "encoding" 12 "io" 13 "reflect" 14 "slices" 15 "strings" 16 "sync" 17 "time" 18 19 "encoding/json/internal" 20 "encoding/json/internal/jsonflags" 21 "encoding/json/internal/jsonopts" 22 "encoding/json/jsontext" 23 ) 24 25 // Reference encoding and time packages to assist pkgsite 26 // in being able to hotlink references to those packages. 27 var ( 28 _ encoding.TextMarshaler 29 _ encoding.TextAppender 30 _ encoding.TextUnmarshaler 31 _ time.Time 32 _ time.Duration 33 ) 34 35 // export exposes internal functionality of the "jsontext" package. 36 var export = jsontext.Internal.Export(&internal.AllowInternalUse) 37 38 // Marshal serializes a Go value as a []byte according to the provided 39 // marshal and encode options (while ignoring unmarshal or decode options). 40 // It does not terminate the output with a newline. 41 // 42 // Type-specific marshal functions and methods take precedence 43 // over the default representation of a value. 44 // Functions or methods that operate on *T are only called when encoding 45 // a value of type T (by taking its address) or a non-nil value of *T. 46 // Marshal ensures that a value is always addressable 47 // (by boxing it on the heap if necessary) so that 48 // these functions and methods can be consistently called. For performance, 49 // it is recommended that Marshal be passed a non-nil pointer to the value. 50 // 51 // The input value is encoded as JSON according the following rules: 52 // 53 // - If any type-specific functions in a [WithMarshalers] option match 54 // the value type, then those functions are called to encode the value. 55 // If all applicable functions return [SkipFunc], 56 // then the value is encoded according to subsequent rules. 57 // 58 // - If the value type implements [MarshalerTo], 59 // then the MarshalJSONTo method is called to encode the value. 60 // 61 // - If the value type implements [Marshaler], 62 // then the MarshalJSON method is called to encode the value. 63 // 64 // - If the value type implements [encoding.TextAppender], 65 // then the AppendText method is called to encode the value and 66 // subsequently encode its result as a JSON string. 67 // 68 // - If the value type implements [encoding.TextMarshaler], 69 // then the MarshalText method is called to encode the value and 70 // subsequently encode its result as a JSON string. 71 // 72 // - Otherwise, the value is encoded according to the value's type 73 // as described in detail below. 74 // 75 // Most Go types have a default JSON representation. 76 // Certain types support specialized formatting according to 77 // a format flag optionally specified in the Go struct tag 78 // for the struct field that contains the current value 79 // (see the “JSON Representation of Go structs” section for more details). 80 // 81 // The representation of each type is as follows: 82 // 83 // - A Go boolean is encoded as a JSON boolean (e.g., true or false). 84 // It does not support any custom format flags. 85 // 86 // - A Go string is encoded as a JSON string. 87 // It does not support any custom format flags. 88 // 89 // - A Go []byte or [N]byte is encoded as a JSON string containing 90 // the binary value encoded using RFC 4648. 91 // If the format is "base64" or unspecified, then this uses RFC 4648, section 4. 92 // If the format is "base64url", then this uses RFC 4648, section 5. 93 // If the format is "base32", then this uses RFC 4648, section 6. 94 // If the format is "base32hex", then this uses RFC 4648, section 7. 95 // If the format is "base16" or "hex", then this uses RFC 4648, section 8. 96 // If the format is "array", then the bytes value is encoded as a JSON array 97 // where each byte is recursively JSON-encoded as each JSON array element. 98 // 99 // - A Go integer is encoded as a JSON number without fractions or exponents. 100 // If [StringifyNumbers] is specified or encoding a JSON object name, 101 // then the JSON number is encoded within a JSON string. 102 // It does not support any custom format flags. 103 // 104 // - A Go float is encoded as a JSON number. 105 // If [StringifyNumbers] is specified or encoding a JSON object name, 106 // then the JSON number is encoded within a JSON string. 107 // If the format is "nonfinite", then NaN, +Inf, and -Inf are encoded as 108 // the JSON strings "NaN", "Infinity", and "-Infinity", respectively. 109 // Otherwise, the presence of non-finite numbers results in a [SemanticError]. 110 // 111 // - A Go map is encoded as a JSON object, where each Go map key and value 112 // is recursively encoded as a name and value pair in the JSON object. 113 // The Go map key must encode as a JSON string, otherwise this results 114 // in a [SemanticError]. The Go map is traversed in a non-deterministic order. 115 // For deterministic encoding, consider using the [Deterministic] option. 116 // If the format is "emitnull", then a nil map is encoded as a JSON null. 117 // If the format is "emitempty", then a nil map is encoded as an empty JSON object, 118 // regardless of whether [FormatNilMapAsNull] is specified. 119 // Otherwise by default, a nil map is encoded as an empty JSON object. 120 // 121 // - A Go struct is encoded as a JSON object. 122 // See the “JSON Representation of Go structs” section 123 // in the package-level documentation for more details. 124 // 125 // - A Go slice is encoded as a JSON array, where each Go slice element 126 // is recursively JSON-encoded as the elements of the JSON array. 127 // If the format is "emitnull", then a nil slice is encoded as a JSON null. 128 // If the format is "emitempty", then a nil slice is encoded as an empty JSON array, 129 // regardless of whether [FormatNilSliceAsNull] is specified. 130 // Otherwise by default, a nil slice is encoded as an empty JSON array. 131 // 132 // - A Go array is encoded as a JSON array, where each Go array element 133 // is recursively JSON-encoded as the elements of the JSON array. 134 // The JSON array length is always identical to the Go array length. 135 // It does not support any custom format flags. 136 // 137 // - A Go pointer is encoded as a JSON null if nil, otherwise it is 138 // the recursively JSON-encoded representation of the underlying value. 139 // Format flags are forwarded to the encoding of the underlying value. 140 // 141 // - A Go interface is encoded as a JSON null if nil, otherwise it is 142 // the recursively JSON-encoded representation of the underlying value. 143 // It does not support any custom format flags. 144 // 145 // - A Go [time.Time] is encoded as a JSON string containing the timestamp 146 // formatted in RFC 3339 with nanosecond precision. 147 // If the format matches one of the format constants declared 148 // in the time package (e.g., RFC1123), then that format is used. 149 // If the format is "unix", "unixmilli", "unixmicro", or "unixnano", 150 // then the timestamp is encoded as a possibly fractional JSON number 151 // of the number of seconds (or milliseconds, microseconds, or nanoseconds) 152 // since the Unix epoch, which is January 1st, 1970 at 00:00:00 UTC. 153 // To avoid a fractional component, round the timestamp to the relevant unit. 154 // Otherwise, the format is used as-is with [time.Time.Format] if non-empty. 155 // 156 // - A Go [time.Duration] currently has no default representation and 157 // requires an explicit format to be specified. 158 // If the format is "sec", "milli", "micro", or "nano", 159 // then the duration is encoded as a possibly fractional JSON number 160 // of the number of seconds (or milliseconds, microseconds, or nanoseconds). 161 // To avoid a fractional component, round the duration to the relevant unit. 162 // If the format is "units", it is encoded as a JSON string formatted using 163 // [time.Duration.String] (e.g., "1h30m" for 1 hour 30 minutes). 164 // If the format is "iso8601", it is encoded as a JSON string using the 165 // ISO 8601 standard for durations (e.g., "PT1H30M" for 1 hour 30 minutes) 166 // using only accurate units of hours, minutes, and seconds. 167 // 168 // - All other Go types (e.g., complex numbers, channels, and functions) 169 // have no default representation and result in a [SemanticError]. 170 // 171 // JSON cannot represent cyclic data structures and Marshal does not handle them. 172 // Passing cyclic structures will result in an error. 173 func Marshal(in any, opts ...Options) (out []byte, err error) { 174 enc := export.GetBufferedEncoder(opts...) 175 defer export.PutBufferedEncoder(enc) 176 xe := export.Encoder(enc) 177 xe.Flags.Set(jsonflags.OmitTopLevelNewline | 1) 178 err = marshalEncode(enc, in, &xe.Struct) 179 if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 180 return nil, internal.TransformMarshalError(in, err) 181 } 182 return bytes.Clone(xe.Buf), err 183 } 184 185 // MarshalWrite serializes a Go value into an [io.Writer] according to the provided 186 // marshal and encode options (while ignoring unmarshal or decode options). 187 // It does not terminate the output with a newline. 188 // See [Marshal] for details about the conversion of a Go value into JSON. 189 func MarshalWrite(out io.Writer, in any, opts ...Options) (err error) { 190 enc := export.GetStreamingEncoder(out, opts...) 191 defer export.PutStreamingEncoder(enc) 192 xe := export.Encoder(enc) 193 xe.Flags.Set(jsonflags.OmitTopLevelNewline | 1) 194 err = marshalEncode(enc, in, &xe.Struct) 195 if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 196 return internal.TransformMarshalError(in, err) 197 } 198 return err 199 } 200 201 // MarshalEncode serializes a Go value into an [jsontext.Encoder] according to 202 // the provided marshal options (while ignoring unmarshal, encode, or decode options). 203 // Any marshal-relevant options already specified on the [jsontext.Encoder] 204 // take lower precedence than the set of options provided by the caller. 205 // Unlike [Marshal] and [MarshalWrite], encode options are ignored because 206 // they must have already been specified on the provided [jsontext.Encoder]. 207 // 208 // See [Marshal] for details about the conversion of a Go value into JSON. 209 func MarshalEncode(out *jsontext.Encoder, in any, opts ...Options) (err error) { 210 xe := export.Encoder(out) 211 if len(opts) > 0 { 212 optsOriginal := xe.Struct 213 defer func() { xe.Struct = optsOriginal }() 214 xe.Struct.JoinWithoutCoderOptions(opts...) 215 } 216 err = marshalEncode(out, in, &xe.Struct) 217 if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 218 return internal.TransformMarshalError(in, err) 219 } 220 return err 221 } 222 223 func marshalEncode(out *jsontext.Encoder, in any, mo *jsonopts.Struct) (err error) { 224 v := reflect.ValueOf(in) 225 if !v.IsValid() || (v.Kind() == reflect.Pointer && v.IsNil()) { 226 return out.WriteToken(jsontext.Null) 227 } 228 // Shallow copy non-pointer values to obtain an addressable value. 229 // It is beneficial to performance to always pass pointers to avoid this. 230 forceAddr := v.Kind() != reflect.Pointer 231 if forceAddr { 232 v2 := reflect.New(v.Type()) 233 v2.Elem().Set(v) 234 v = v2 235 } 236 va := addressableValue{v.Elem(), forceAddr} // dereferenced pointer is always addressable 237 t := va.Type() 238 239 // Lookup and call the marshal function for this type. 240 marshal := lookupArshaler(t).marshal 241 if mo.Marshalers != nil { 242 marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t) 243 } 244 if err := marshal(out, va, mo); err != nil { 245 if !mo.Flags.Get(jsonflags.AllowDuplicateNames) { 246 export.Encoder(out).Tokens.InvalidateDisabledNamespaces() 247 } 248 return err 249 } 250 return nil 251 } 252 253 // Unmarshal decodes a []byte input into a Go value according to the provided 254 // unmarshal and decode options (while ignoring marshal or encode options). 255 // The input must be a single JSON value with optional whitespace interspersed. 256 // The output must be a non-nil pointer. 257 // 258 // Type-specific unmarshal functions and methods take precedence 259 // over the default representation of a value. 260 // Functions or methods that operate on *T are only called when decoding 261 // a value of type T (by taking its address) or a non-nil value of *T. 262 // Unmarshal ensures that a value is always addressable 263 // (by boxing it on the heap if necessary) so that 264 // these functions and methods can be consistently called. 265 // 266 // The input is decoded into the output according the following rules: 267 // 268 // - If any type-specific functions in a [WithUnmarshalers] option match 269 // the value type, then those functions are called to decode the JSON 270 // value. If all applicable functions return [SkipFunc], 271 // then the input is decoded according to subsequent rules. 272 // 273 // - If the value type implements [UnmarshalerFrom], 274 // then the UnmarshalJSONFrom method is called to decode the JSON value. 275 // 276 // - If the value type implements [Unmarshaler], 277 // then the UnmarshalJSON method is called to decode the JSON value. 278 // 279 // - If the value type implements [encoding.TextUnmarshaler], 280 // then the input is decoded as a JSON string and 281 // the UnmarshalText method is called with the decoded string value. 282 // This fails with a [SemanticError] if the input is not a JSON string. 283 // 284 // - Otherwise, the JSON value is decoded according to the value's type 285 // as described in detail below. 286 // 287 // Most Go types have a default JSON representation. 288 // Certain types support specialized formatting according to 289 // a format flag optionally specified in the Go struct tag 290 // for the struct field that contains the current value 291 // (see the “JSON Representation of Go structs” section for more details). 292 // A JSON null may be decoded into every supported Go value where 293 // it is equivalent to storing the zero value of the Go value. 294 // If the input JSON kind is not handled by the current Go value type, 295 // then this fails with a [SemanticError]. Unless otherwise specified, 296 // the decoded value replaces any pre-existing value. 297 // 298 // The representation of each type is as follows: 299 // 300 // - A Go boolean is decoded from a JSON boolean (e.g., true or false). 301 // It does not support any custom format flags. 302 // 303 // - A Go string is decoded from a JSON string. 304 // It does not support any custom format flags. 305 // 306 // - A Go []byte or [N]byte is decoded from a JSON string 307 // containing the binary value encoded using RFC 4648. 308 // If the format is "base64" or unspecified, then this uses RFC 4648, section 4. 309 // If the format is "base64url", then this uses RFC 4648, section 5. 310 // If the format is "base32", then this uses RFC 4648, section 6. 311 // If the format is "base32hex", then this uses RFC 4648, section 7. 312 // If the format is "base16" or "hex", then this uses RFC 4648, section 8. 313 // If the format is "array", then the Go slice or array is decoded from a 314 // JSON array where each JSON element is recursively decoded for each byte. 315 // When decoding into a non-nil []byte, the slice length is reset to zero 316 // and the decoded input is appended to it. 317 // When decoding into a [N]byte, the input must decode to exactly N bytes, 318 // otherwise it fails with a [SemanticError]. 319 // 320 // - A Go integer is decoded from a JSON number. 321 // It must be decoded from a JSON string containing a JSON number 322 // if [StringifyNumbers] is specified or decoding a JSON object name. 323 // It fails with a [SemanticError] if the JSON number 324 // has a fractional or exponent component. 325 // It also fails if it overflows the representation of the Go integer type. 326 // It does not support any custom format flags. 327 // 328 // - A Go float is decoded from a JSON number. 329 // It must be decoded from a JSON string containing a JSON number 330 // if [StringifyNumbers] is specified or decoding a JSON object name. 331 // It fails if it overflows the representation of the Go float type. 332 // If the format is "nonfinite", then the JSON strings 333 // "NaN", "Infinity", and "-Infinity" are decoded as NaN, +Inf, and -Inf. 334 // Otherwise, the presence of such strings results in a [SemanticError]. 335 // 336 // - A Go map is decoded from a JSON object, 337 // where each JSON object name and value pair is recursively decoded 338 // as the Go map key and value. Maps are not cleared. 339 // If the Go map is nil, then a new map is allocated to decode into. 340 // If the decoded key matches an existing Go map entry, the entry value 341 // is reused by decoding the JSON object value into it. 342 // The formats "emitnull" and "emitempty" have no effect when decoding. 343 // 344 // - A Go struct is decoded from a JSON object. 345 // See the “JSON Representation of Go structs” section 346 // in the package-level documentation for more details. 347 // 348 // - A Go slice is decoded from a JSON array, where each JSON element 349 // is recursively decoded and appended to the Go slice. 350 // Before appending into a Go slice, a new slice is allocated if it is nil, 351 // otherwise the slice length is reset to zero. 352 // The formats "emitnull" and "emitempty" have no effect when decoding. 353 // 354 // - A Go array is decoded from a JSON array, where each JSON array element 355 // is recursively decoded as each corresponding Go array element. 356 // Each Go array element is zeroed before decoding into it. 357 // It fails with a [SemanticError] if the JSON array does not contain 358 // the exact same number of elements as the Go array. 359 // It does not support any custom format flags. 360 // 361 // - A Go pointer is decoded based on the JSON kind and underlying Go type. 362 // If the input is a JSON null, then this stores a nil pointer. 363 // Otherwise, it allocates a new underlying value if the pointer is nil, 364 // and recursively JSON decodes into the underlying value. 365 // Format flags are forwarded to the decoding of the underlying type. 366 // 367 // - A Go interface is decoded based on the JSON kind and underlying Go type. 368 // If the input is a JSON null, then this stores a nil interface value. 369 // Otherwise, a nil interface value of an empty interface type is initialized 370 // with a zero Go bool, string, float64, map[string]any, or []any if the 371 // input is a JSON boolean, string, number, object, or array, respectively. 372 // If the interface value is still nil, then this fails with a [SemanticError] 373 // since decoding could not determine an appropriate Go type to decode into. 374 // For example, unmarshaling into a nil io.Reader fails since 375 // there is no concrete type to populate the interface value with. 376 // Otherwise an underlying value exists and it recursively decodes 377 // the JSON input into it. It does not support any custom format flags. 378 // 379 // - A Go [time.Time] is decoded from a JSON string containing the time 380 // formatted in RFC 3339 with nanosecond precision. 381 // If the format matches one of the format constants declared in 382 // the time package (e.g., RFC1123), then that format is used for parsing. 383 // If the format is "unix", "unixmilli", "unixmicro", or "unixnano", 384 // then the timestamp is decoded from an optionally fractional JSON number 385 // of the number of seconds (or milliseconds, microseconds, or nanoseconds) 386 // since the Unix epoch, which is January 1st, 1970 at 00:00:00 UTC. 387 // Otherwise, the format is used as-is with [time.Time.Parse] if non-empty. 388 // 389 // - A Go [time.Duration] currently has no default representation and 390 // requires an explicit format to be specified. 391 // If the format is "sec", "milli", "micro", or "nano", 392 // then the duration is decoded from an optionally fractional JSON number 393 // of the number of seconds (or milliseconds, microseconds, or nanoseconds). 394 // If the format is "units", it is decoded from a JSON string parsed using 395 // [time.ParseDuration] (e.g., "1h30m" for 1 hour 30 minutes). 396 // If the format is "iso8601", it is decoded from a JSON string using the 397 // ISO 8601 standard for durations (e.g., "PT1H30M" for 1 hour 30 minutes) 398 // accepting only accurate units of hours, minutes, or seconds. 399 // 400 // - All other Go types (e.g., complex numbers, channels, and functions) 401 // have no default representation and result in a [SemanticError]. 402 // 403 // In general, unmarshaling follows merge semantics (similar to RFC 7396) 404 // where the decoded Go value replaces the destination value 405 // for any JSON kind other than an object. 406 // For JSON objects, the input object is merged into the destination value 407 // where matching object members recursively apply merge semantics. 408 func Unmarshal(in []byte, out any, opts ...Options) (err error) { 409 dec := export.GetBufferedDecoder(in, opts...) 410 defer export.PutBufferedDecoder(dec) 411 xd := export.Decoder(dec) 412 err = unmarshalFull(dec, out, &xd.Struct) 413 if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 414 return internal.TransformUnmarshalError(out, err) 415 } 416 return err 417 } 418 419 // UnmarshalRead deserializes a Go value from an [io.Reader] according to the 420 // provided unmarshal and decode options (while ignoring marshal or encode options). 421 // The input must be a single JSON value with optional whitespace interspersed. 422 // It consumes the entirety of [io.Reader] until [io.EOF] is encountered, 423 // without reporting an error for EOF. The output must be a non-nil pointer. 424 // See [Unmarshal] for details about the conversion of JSON into a Go value. 425 func UnmarshalRead(in io.Reader, out any, opts ...Options) (err error) { 426 dec := export.GetStreamingDecoder(in, opts...) 427 defer export.PutStreamingDecoder(dec) 428 xd := export.Decoder(dec) 429 err = unmarshalFull(dec, out, &xd.Struct) 430 if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 431 return internal.TransformUnmarshalError(out, err) 432 } 433 return err 434 } 435 436 func unmarshalFull(in *jsontext.Decoder, out any, uo *jsonopts.Struct) error { 437 switch err := unmarshalDecode(in, out, uo); err { 438 case nil: 439 return export.Decoder(in).CheckEOF() 440 case io.EOF: 441 return io.ErrUnexpectedEOF 442 default: 443 return err 444 } 445 } 446 447 // UnmarshalDecode deserializes a Go value from a [jsontext.Decoder] according to 448 // the provided unmarshal options (while ignoring marshal, encode, or decode options). 449 // Any unmarshal options already specified on the [jsontext.Decoder] 450 // take lower precedence than the set of options provided by the caller. 451 // Unlike [Unmarshal] and [UnmarshalRead], decode options are ignored because 452 // they must have already been specified on the provided [jsontext.Decoder]. 453 // 454 // The input may be a stream of one or more JSON values, 455 // where this only unmarshals the next JSON value in the stream. 456 // The output must be a non-nil pointer. 457 // See [Unmarshal] for details about the conversion of JSON into a Go value. 458 func UnmarshalDecode(in *jsontext.Decoder, out any, opts ...Options) (err error) { 459 xd := export.Decoder(in) 460 if len(opts) > 0 { 461 optsOriginal := xd.Struct 462 defer func() { xd.Struct = optsOriginal }() 463 xd.Struct.JoinWithoutCoderOptions(opts...) 464 } 465 err = unmarshalDecode(in, out, &xd.Struct) 466 if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 467 return internal.TransformUnmarshalError(out, err) 468 } 469 return err 470 } 471 472 func unmarshalDecode(in *jsontext.Decoder, out any, uo *jsonopts.Struct) (err error) { 473 v := reflect.ValueOf(out) 474 if v.Kind() != reflect.Pointer || v.IsNil() { 475 return &SemanticError{action: "unmarshal", GoType: reflect.TypeOf(out), Err: internal.ErrNonNilReference} 476 } 477 va := addressableValue{v.Elem(), false} // dereferenced pointer is always addressable 478 t := va.Type() 479 480 // In legacy semantics, the entirety of the next JSON value 481 // was validated before attempting to unmarshal it. 482 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 483 if err := export.Decoder(in).CheckNextValue(); err != nil { 484 return err 485 } 486 } 487 488 // Lookup and call the unmarshal function for this type. 489 unmarshal := lookupArshaler(t).unmarshal 490 if uo.Unmarshalers != nil { 491 unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t) 492 } 493 if err := unmarshal(in, va, uo); err != nil { 494 if !uo.Flags.Get(jsonflags.AllowDuplicateNames) { 495 export.Decoder(in).Tokens.InvalidateDisabledNamespaces() 496 } 497 return err 498 } 499 return nil 500 } 501 502 // addressableValue is a reflect.Value that is guaranteed to be addressable 503 // such that calling the Addr and Set methods do not panic. 504 // 505 // There is no compile magic that enforces this property, 506 // but rather the need to construct this type makes it easier to examine each 507 // construction site to ensure that this property is upheld. 508 type addressableValue struct { 509 reflect.Value 510 511 // forcedAddr reports whether this value is addressable 512 // only through the use of [newAddressableValue]. 513 // This is only used for [jsonflags.CallMethodsWithLegacySemantics]. 514 forcedAddr bool 515 } 516 517 // newAddressableValue constructs a new addressable value of type t. 518 func newAddressableValue(t reflect.Type) addressableValue { 519 return addressableValue{reflect.New(t).Elem(), true} 520 } 521 522 // TODO: Remove *jsonopts.Struct argument from [marshaler] and [unmarshaler]. 523 // This can be directly accessed on the encoder or decoder. 524 525 // All marshal and unmarshal behavior is implemented using these signatures. 526 // The *jsonopts.Struct argument is guaranteed to identical to or at least 527 // a strict super-set of the options in Encoder.Struct or Decoder.Struct. 528 // It is identical for Marshal, Unmarshal, MarshalWrite, and UnmarshalRead. 529 // It is a super-set for MarshalEncode and UnmarshalDecode. 530 type ( 531 marshaler = func(*jsontext.Encoder, addressableValue, *jsonopts.Struct) error 532 unmarshaler = func(*jsontext.Decoder, addressableValue, *jsonopts.Struct) error 533 ) 534 535 type arshaler struct { 536 marshal marshaler 537 unmarshal unmarshaler 538 nonDefault bool 539 } 540 541 var lookupArshalerCache sync.Map // map[reflect.Type]*arshaler 542 543 func lookupArshaler(t reflect.Type) *arshaler { 544 if v, ok := lookupArshalerCache.Load(t); ok { 545 return v.(*arshaler) 546 } 547 548 fncs := makeDefaultArshaler(t) 549 fncs = makeMethodArshaler(fncs, t) 550 fncs = makeTimeArshaler(fncs, t) 551 552 // Use the last stored so that duplicate arshalers can be garbage collected. 553 v, _ := lookupArshalerCache.LoadOrStore(t, fncs) 554 return v.(*arshaler) 555 } 556 557 var stringsPools = &sync.Pool{New: func() any { return new(stringSlice) }} 558 559 type stringSlice []string 560 561 // getStrings returns a non-nil pointer to a slice with length n. 562 func getStrings(n int) *stringSlice { 563 s := stringsPools.Get().(*stringSlice) 564 if cap(*s) < n { 565 *s = make([]string, n) 566 } 567 *s = (*s)[:n] 568 return s 569 } 570 571 func putStrings(s *stringSlice) { 572 if cap(*s) > 1<<10 { 573 *s = nil // avoid pinning arbitrarily large amounts of memory 574 } 575 stringsPools.Put(s) 576 } 577 578 func (ss *stringSlice) Sort() { 579 slices.SortFunc(*ss, func(x, y string) int { return strings.Compare(x, y) }) 580 } 581