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