Source file src/encoding/json/v2_options.go

     1  // Copyright 2023 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  // Migrating to v2
     8  //
     9  // This package (i.e., [encoding/json]) is now formally known as the v1 package
    10  // since a v2 package now exists at [encoding/json/v2].
    11  // All the behavior of the v1 package is implemented in terms of
    12  // the v2 package with the appropriate set of options specified that
    13  // preserve the historical behavior of v1.
    14  //
    15  // The [jsonv2.Marshal] function is the newer equivalent of v1 [Marshal].
    16  // The [jsonv2.Unmarshal] function is the newer equivalent of v1 [Unmarshal].
    17  // The v2 functions have the same calling signature as the v1 equivalent
    18  // except that they take in variadic [Options] arguments that can be specified
    19  // to alter the behavior of marshal or unmarshal. Both v1 and v2 generally
    20  // behave in similar ways, but there are some notable differences.
    21  //
    22  // The following is a list of differences between v1 and v2:
    23  //
    24  //   - In v1, JSON object members are unmarshaled into a Go struct using a
    25  //     case-insensitive name match with the JSON name of the fields.
    26  //     In contrast, v2 matches fields using an exact, case-sensitive match.
    27  //     The [jsonv2.MatchCaseInsensitiveNames] and [MatchCaseSensitiveDelimiter]
    28  //     options control this behavior difference. To explicitly specify a Go struct
    29  //     field to use a particular name matching scheme, either the `case:ignore`
    30  //     or the `case:strict` field option can be specified.
    31  //     Field-specified options take precedence over caller-specified options.
    32  //
    33  //   - In v1, when marshaling a Go struct, a field marked as `omitempty`
    34  //     is omitted if the field value is an "empty" Go value, which is defined as
    35  //     false, 0, a nil pointer, a nil interface value, and
    36  //     any empty array, slice, map, or string. In contrast, v2 redefines
    37  //     `omitempty` to omit a field if it encodes as an "empty" JSON value,
    38  //     which is defined as a JSON null, or an empty JSON string, object, or array.
    39  //     The [OmitEmptyWithLegacySemantics] option controls this behavior difference.
    40  //     Note that `omitempty` behaves identically in both v1 and v2 for a
    41  //     Go array, slice, map, or string (assuming no user-defined MarshalJSON method
    42  //     overrides the default representation). Existing usages of `omitempty` on a
    43  //     Go bool, number, pointer, or interface value should migrate to specifying
    44  //     `omitzero` instead (which is identically supported in both v1 and v2).
    45  //
    46  //   - In v1, a Go struct field marked as `string` can be used to quote a
    47  //     Go string, bool, number, or pointer to such as a JSON string.
    48  //     In contrast, v2 restricts the `string` option to only quote a value
    49  //     that would normally be represented as a JSON number,
    50  //     but also expands support for it to operate with any Go type
    51  //     that would normally be represented as a JSON number.
    52  //     The [StringifyWithLegacySemantics] option controls this behavior difference.
    53  //
    54  //   - In v1, a nil Go slice or Go map is marshaled as a JSON null.
    55  //     In contrast, v2 marshals a nil Go slice or Go map as
    56  //     an empty JSON array or JSON object, respectively.
    57  //     The [jsonv2.FormatNilSliceAsNull] and [jsonv2.FormatNilMapAsNull] options
    58  //     control this behavior difference.
    59  //
    60  //   - In v1, a Go array may be unmarshaled from a JSON array of any length.
    61  //     In contrast, in v2 a Go array must be unmarshaled from a JSON array
    62  //     of the same length, otherwise it results in an error.
    63  //     The [UnmarshalArrayFromAnyLength] option controls this behavior difference.
    64  //
    65  //   - In v1, a Go byte array is represented as a JSON array of JSON numbers.
    66  //     In contrast, in v2 a Go byte array is represented as a Base64-encoded JSON string.
    67  //     The [FormatByteArrayAsArray] option controls this behavior difference.
    68  //
    69  //   - In v1, MarshalJSON methods declared on a pointer receiver are only called
    70  //     if the Go value is addressable. In contrast, in v2 a MarshalJSON method
    71  //     is always callable regardless of addressability.
    72  //     The [CallMethodsWithLegacySemantics] option controls this behavior difference.
    73  //
    74  //   - In v1, MarshalJSON and UnmarshalJSON methods are never called for Go map keys.
    75  //     In contrast, in v2 a MarshalJSON or UnmarshalJSON method is eligible for
    76  //     being called for Go map keys.
    77  //     The [CallMethodsWithLegacySemantics] option controls this behavior difference.
    78  //
    79  //   - In v1, a Go map is marshaled in a deterministic order.
    80  //     In contrast, in v2 a Go map is marshaled in a non-deterministic order.
    81  //     The [jsonv2.Deterministic] option controls this behavior difference.
    82  //
    83  //   - In v1, JSON strings are encoded with HTML-specific or JavaScript-specific
    84  //     characters being escaped. In contrast, in v2 JSON strings use the minimal
    85  //     encoding and only escape if required by the JSON grammar.
    86  //     The [jsontext.EscapeForHTML] and [jsontext.EscapeForJS] options
    87  //     control this behavior difference.
    88  //
    89  //   - In v1, bytes of invalid UTF-8 within a string are silently replaced with
    90  //     the Unicode replacement character. In contrast, in v2 the presence of
    91  //     invalid UTF-8 results in an error. The [jsontext.AllowInvalidUTF8] option
    92  //     controls this behavior difference.
    93  //
    94  //   - In v1, a JSON object with duplicate names is permitted.
    95  //     In contrast, in v2 a JSON object with duplicate names results in an error.
    96  //     The [jsontext.AllowDuplicateNames] option controls this behavior difference.
    97  //
    98  //   - In v1, when unmarshaling a JSON null into a non-empty Go value it will
    99  //     inconsistently either zero out the value or do nothing.
   100  //     In contrast, in v2 unmarshaling a JSON null will consistently and always
   101  //     zero out the underlying Go value. The [MergeWithLegacySemantics] option
   102  //     controls this behavior difference.
   103  //
   104  //   - In v1, when unmarshaling a JSON value into a non-zero Go value,
   105  //     it merges into the original Go value for array elements, slice elements,
   106  //     struct fields (but not map values),
   107  //     pointer values, and interface values (only if a non-nil pointer).
   108  //     In contrast, in v2 unmarshal merges into the Go value
   109  //     for struct fields, map values, pointer values, and interface values.
   110  //     In general, the v2 semantic merges when unmarshaling a JSON object,
   111  //     otherwise it replaces the value. The [MergeWithLegacySemantics] option
   112  //     controls this behavior difference.
   113  //
   114  //   - In v1, a [time.Duration] is represented as a JSON number containing
   115  //     the decimal number of nanoseconds. In contrast, in v2 a [time.Duration]
   116  //     has no default representation and results in a runtime error.
   117  //     The [FormatDurationAsNano] option controls this behavior difference.
   118  //
   119  //   - In v1, errors are never reported at runtime for Go struct types
   120  //     that have some form of structural error (e.g., a malformed tag option).
   121  //     In contrast, v2 reports a runtime error for Go types that are invalid
   122  //     as they relate to JSON serialization. For example, a Go struct
   123  //     with only unexported fields cannot be serialized.
   124  //     The [ReportErrorsWithLegacySemantics] option controls this behavior difference.
   125  //
   126  // As mentioned, the entirety of v1 is implemented in terms of v2,
   127  // where options are implicitly specified to opt into legacy behavior.
   128  // For example, [Marshal] directly calls [jsonv2.Marshal] with [DefaultOptionsV1].
   129  // Similarly, [Unmarshal] directly calls [jsonv2.Unmarshal] with [DefaultOptionsV1].
   130  // The [DefaultOptionsV1] option represents the set of all options that specify
   131  // default v1 behavior.
   132  //
   133  // For many of the behavior differences, there are Go struct field options
   134  // that the author of a Go type can specify to control the behavior such that
   135  // the type is represented identically in JSON under either v1 or v2 semantics.
   136  //
   137  // The availability of [DefaultOptionsV1] and [jsonv2.DefaultOptionsV2],
   138  // where later options take precedence over former options allows for
   139  // a gradual migration from v1 to v2. For example:
   140  //
   141  //   - jsonv1.Marshal(v)
   142  //     uses default v1 semantics.
   143  //
   144  //   - jsonv2.Marshal(v, jsonv1.DefaultOptionsV1())
   145  //     is semantically equivalent to jsonv1.Marshal
   146  //     and thus uses default v1 semantics.
   147  //
   148  //   - jsonv2.Marshal(v, jsonv1.DefaultOptionsV1(), jsontext.AllowDuplicateNames(false))
   149  //     uses mostly v1 semantics, but opts into one particular v2-specific behavior.
   150  //
   151  //   - jsonv2.Marshal(v, jsonv1.CallMethodsWithLegacySemantics(true))
   152  //     uses mostly v2 semantics, but opts into one particular v1-specific behavior.
   153  //
   154  //   - jsonv2.Marshal(v, ..., jsonv2.DefaultOptionsV2())
   155  //     is semantically equivalent to jsonv2.Marshal since
   156  //     jsonv2.DefaultOptionsV2 overrides any options specified earlier
   157  //     and thus uses default v2 semantics.
   158  //
   159  //   - jsonv2.Marshal(v)
   160  //     uses default v2 semantics.
   161  //
   162  // All new usages of "json" in Go should use the v2 package,
   163  // but the v1 package will forever remain supported.
   164  //
   165  // See the [encoding/json/v2 Migration Guide] for additional detail on migration approaches.
   166  //
   167  // [encoding/json/v2 Migration Guide]: https://go.dev/doc/jsonv2-migration
   168  package json
   169  
   170  // TODO(https://go.dev/issue/71631): Update the "Migrating to v2" documentation
   171  // with default v2 behavior for [time.Duration].
   172  
   173  import (
   174  	"encoding"
   175  
   176  	"encoding/json/internal/jsonflags"
   177  	"encoding/json/internal/jsonopts"
   178  	"encoding/json/jsontext"
   179  	jsonv2 "encoding/json/v2"
   180  )
   181  
   182  // Reference encoding, jsonv2, and jsontext packages to assist pkgsite
   183  // in being able to hotlink references to those packages.
   184  var (
   185  	_ encoding.TextMarshaler
   186  	_ encoding.TextUnmarshaler
   187  	_ jsonv2.Options
   188  	_ jsontext.Options
   189  )
   190  
   191  // Options are a set of options to configure the v2 "json" package
   192  // to operate with v1 semantics for particular features.
   193  // Values of this type can be passed to v2 functions like
   194  // [jsonv2.Marshal] or [jsonv2.Unmarshal].
   195  // Instead of referencing this type, use [jsonv2.Options].
   196  //
   197  // See the "Migrating to v2" section for guidance on how to migrate usage
   198  // of "json" from using v1 to using v2 instead.
   199  type Options = jsonopts.Options
   200  
   201  // DefaultOptionsV1 is the full set of all options that define v1 semantics.
   202  // It is equivalent to the following boolean options being set to true:
   203  //
   204  //   - [CallMethodsWithLegacySemantics]
   205  //   - [FormatByteArrayAsArray]
   206  //   - [FormatBytesWithLegacySemantics]
   207  //   - [FormatDurationAsNano]
   208  //   - [MatchCaseSensitiveDelimiter]
   209  //   - [MergeWithLegacySemantics]
   210  //   - [OmitEmptyWithLegacySemantics]
   211  //   - [ParseBytesWithLooseRFC4648]
   212  //   - [ParseTimeWithLooseRFC3339]
   213  //   - [ReportErrorsWithLegacySemantics]
   214  //   - [StringifyWithLegacySemantics]
   215  //   - [UnmarshalArrayFromAnyLength]
   216  //   - [jsonv2.Deterministic]
   217  //   - [jsonv2.FormatNilMapAsNull]
   218  //   - [jsonv2.FormatNilSliceAsNull]
   219  //   - [jsonv2.MatchCaseInsensitiveNames]
   220  //   - [jsontext.AllowDuplicateNames]
   221  //   - [jsontext.AllowInvalidUTF8]
   222  //   - [jsontext.EscapeForHTML]
   223  //   - [jsontext.EscapeForJS]
   224  //   - [jsontext.PreserveRawStrings]
   225  //
   226  // All other options are not present.
   227  //
   228  // The [Marshal] and [Unmarshal] functions in this package are
   229  // semantically identical to calling the v2 equivalents with this option:
   230  //
   231  //	jsonv2.Marshal(v, jsonv1.DefaultOptionsV1())
   232  //	jsonv2.Unmarshal(b, v, jsonv1.DefaultOptionsV1())
   233  func DefaultOptionsV1() Options {
   234  	return &jsonopts.DefaultOptionsV1
   235  }
   236  
   237  // CallMethodsWithLegacySemantics specifies that calling of type-provided
   238  // marshal and unmarshal methods follow legacy semantics:
   239  //
   240  //   - When marshaling, a marshal method declared on a pointer receiver
   241  //     is only called if the Go value is addressable.
   242  //     Values obtained from an interface or map element are not addressable.
   243  //     Values obtained from a pointer or slice element are addressable.
   244  //     Values obtained from an array element or struct field inherit
   245  //     the addressability of the parent. In contrast, the v2 semantic
   246  //     is to always call marshal methods regardless of addressability.
   247  //
   248  //   - When marshaling or unmarshaling, the [Marshaler] or [Unmarshaler]
   249  //     methods are ignored for map keys. However, [encoding.TextMarshaler]
   250  //     or [encoding.TextUnmarshaler] are still callable.
   251  //     In contrast, the v2 semantic is to serialize map keys
   252  //     like any other value (with regard to calling methods),
   253  //     which may include calling [Marshaler] or [Unmarshaler] methods,
   254  //     where it is the implementation's responsibility to represent the
   255  //     Go value as a JSON string (as required for JSON object names).
   256  //
   257  //   - When marshaling, if a map key value implements a marshal method
   258  //     and is a nil pointer, then it is serialized as an empty JSON string.
   259  //     In contrast, the v2 semantic is to report an error.
   260  //
   261  //   - When marshaling, if an interface type implements a marshal method
   262  //     and the interface value is a nil pointer to a concrete type,
   263  //     then the marshal method is always called.
   264  //     In contrast, the v2 semantic is to never directly call methods
   265  //     on interface values and to instead defer evaluation based upon
   266  //     the underlying concrete value. Similar to non-interface values,
   267  //     marshal methods are not called on nil pointers and
   268  //     are instead serialized as a JSON null.
   269  //
   270  // This affects either marshaling or unmarshaling.
   271  // The v1 default is true.
   272  func CallMethodsWithLegacySemantics(v bool) Options {
   273  	if v {
   274  		return jsonflags.CallMethodsWithLegacySemantics | 1
   275  	} else {
   276  		return jsonflags.CallMethodsWithLegacySemantics | 0
   277  	}
   278  }
   279  
   280  // FormatByteArrayAsArray specifies that a Go [N]byte is
   281  // formatted as a normal Go array in contrast to the v2 default of
   282  // formatting [N]byte as using binary data encoding (RFC 4648).
   283  //
   284  // This affects either marshaling or unmarshaling.
   285  // The v1 default is true.
   286  func FormatByteArrayAsArray(v bool) Options {
   287  	if v {
   288  		return jsonflags.FormatByteArrayAsArray | 1
   289  	} else {
   290  		return jsonflags.FormatByteArrayAsArray | 0
   291  	}
   292  }
   293  
   294  // FormatBytesWithLegacySemantics specifies that handling of
   295  // []~byte and [N]~byte types follow legacy semantics:
   296  //
   297  //   - A Go []~byte is to be treated as using some form of
   298  //     binary data encoding (RFC 4648) in contrast to the v2 default
   299  //     of only treating []byte as such. In particular, v2 does not
   300  //     treat slices of named byte types as representing binary data.
   301  //
   302  //   - When marshaling, if a named byte implements a marshal method,
   303  //     then the slice is serialized as a JSON array of elements,
   304  //     each of which call the marshal method.
   305  //
   306  //   - When unmarshaling, if the input is a JSON array,
   307  //     then unmarshal into the []~byte as if it were a normal Go slice.
   308  //     In contrast, the v2 default is to report an error unmarshaling
   309  //     a JSON array when expecting some form of binary data encoding.
   310  //
   311  // This affects either marshaling or unmarshaling.
   312  // The v1 default is true.
   313  func FormatBytesWithLegacySemantics(v bool) Options {
   314  	if v {
   315  		return jsonflags.FormatBytesWithLegacySemantics | 1
   316  	} else {
   317  		return jsonflags.FormatBytesWithLegacySemantics | 0
   318  	}
   319  }
   320  
   321  // FormatDurationAsNano specifies that a [time.Duration] is
   322  // formatted as a JSON number representing the number of nanoseconds
   323  // in contrast to the v2 default of reporting an error.
   324  //
   325  // This affects either marshaling or unmarshaling.
   326  // The v1 default is true.
   327  func FormatDurationAsNano(v bool) Options {
   328  	// TODO(https://go.dev/issue/71631): Update documentation with v2 behavior.
   329  	if v {
   330  		return jsonflags.FormatDurationAsNano | 1
   331  	} else {
   332  		return jsonflags.FormatDurationAsNano | 0
   333  	}
   334  }
   335  
   336  // MatchCaseSensitiveDelimiter specifies that underscores and dashes are
   337  // not to be ignored when performing case-insensitive name matching which
   338  // occurs under [jsonv2.MatchCaseInsensitiveNames] or the `case:ignore` tag option.
   339  // Thus, case-insensitive name matching is identical to [strings.EqualFold].
   340  // Use of this option diminishes the ability of case-insensitive matching
   341  // to be able to match common case variants (e.g., "foo_bar" with "fooBar").
   342  //
   343  // This affects either marshaling or unmarshaling.
   344  // The v1 default is true.
   345  func MatchCaseSensitiveDelimiter(v bool) Options {
   346  	if v {
   347  		return jsonflags.MatchCaseSensitiveDelimiter | 1
   348  	} else {
   349  		return jsonflags.MatchCaseSensitiveDelimiter | 0
   350  	}
   351  }
   352  
   353  // MergeWithLegacySemantics specifies that unmarshaling into a non-zero
   354  // Go value follows legacy semantics:
   355  //
   356  //   - When unmarshaling a JSON null, this preserves the original Go value
   357  //     if the kind is a bool, int, uint, float, string, array, or struct.
   358  //     Otherwise, it zeros the Go value.
   359  //     In contrast, the default v2 behavior is to consistently and always
   360  //     zero the Go value when unmarshaling a JSON null into it.
   361  //
   362  //   - When unmarshaling a JSON value other than null, this merges into
   363  //     the original Go value for array elements, slice elements,
   364  //     struct fields (but not map values),
   365  //     pointer values, and interface values (only if a non-nil pointer).
   366  //     For slices, it will merge into the pre-existing value of slice elements
   367  //     even for those past the slice length. If the original slice length
   368  //     was longer than the JSON array, then it is truncated to match.
   369  //     In contrast, the default v2 behavior is to merge into the Go value
   370  //     for struct fields, map values, pointer values, and interface values.
   371  //     In general, the v2 semantic merges when unmarshaling a JSON object,
   372  //     otherwise it replaces the original value.
   373  //
   374  // This only affects unmarshaling and is ignored when marshaling.
   375  // The v1 default is true.
   376  func MergeWithLegacySemantics(v bool) Options {
   377  	if v {
   378  		return jsonflags.MergeWithLegacySemantics | 1
   379  	} else {
   380  		return jsonflags.MergeWithLegacySemantics | 0
   381  	}
   382  }
   383  
   384  // OmitEmptyWithLegacySemantics specifies that the `omitempty` tag option
   385  // follows a definition of empty where a field is omitted if the Go value is
   386  // false, 0, a nil pointer, a nil interface value,
   387  // or any empty array, slice, map, or string.
   388  // This overrides the v2 semantic where a field is empty if the value
   389  // marshals as a JSON null or an empty JSON string, object, or array.
   390  //
   391  // The v1 and v2 definitions of `omitempty` are practically the same for
   392  // Go strings, slices, arrays, and maps. Usages of `omitempty` on
   393  // Go bools, ints, uints, floats, pointers, and interfaces should migrate to use
   394  // the `omitzero` tag option, which omits a field if it is the zero Go value.
   395  //
   396  // This only affects marshaling and is ignored when unmarshaling.
   397  // The v1 default is true.
   398  func OmitEmptyWithLegacySemantics(v bool) Options {
   399  	if v {
   400  		return jsonflags.OmitEmptyWithLegacySemantics | 1
   401  	} else {
   402  		return jsonflags.OmitEmptyWithLegacySemantics | 0
   403  	}
   404  }
   405  
   406  // ParseBytesWithLooseRFC4648 specifies that when parsing
   407  // binary data encoded as "base32" or "base64",
   408  // to ignore the presence of '\r' and '\n' characters.
   409  // In contrast, the v2 default is to report an error in order to be
   410  // strictly compliant with RFC 4648, section 3.3,
   411  // which specifies that non-alphabet characters must be rejected.
   412  //
   413  // This only affects unmarshaling and is ignored when marshaling.
   414  // The v1 default is true.
   415  func ParseBytesWithLooseRFC4648(v bool) Options {
   416  	if v {
   417  		return jsonflags.ParseBytesWithLooseRFC4648 | 1
   418  	} else {
   419  		return jsonflags.ParseBytesWithLooseRFC4648 | 0
   420  	}
   421  }
   422  
   423  // ParseTimeWithLooseRFC3339 specifies that a [time.Time]
   424  // parses according to loose adherence to RFC 3339.
   425  // In particular, it permits historically incorrect representations,
   426  // allowing for deviations in hour format, sub-second separator,
   427  // and timezone representation. In contrast, the default v2 behavior
   428  // is to strictly comply with the grammar specified in RFC 3339.
   429  //
   430  // This only affects unmarshaling and is ignored when marshaling.
   431  // The v1 default is true.
   432  func ParseTimeWithLooseRFC3339(v bool) Options {
   433  	if v {
   434  		return jsonflags.ParseTimeWithLooseRFC3339 | 1
   435  	} else {
   436  		return jsonflags.ParseTimeWithLooseRFC3339 | 0
   437  	}
   438  }
   439  
   440  // ReportErrorsWithLegacySemantics specifies that Marshal and Unmarshal
   441  // should report errors with legacy semantics:
   442  //
   443  //   - When marshaling or unmarshaling, the returned error values are
   444  //     usually of types such as [SyntaxError], [MarshalerError],
   445  //     [UnsupportedTypeError], [UnsupportedValueError],
   446  //     [InvalidUnmarshalError], or [UnmarshalTypeError].
   447  //     In contrast, the v2 semantic is to always return errors as either
   448  //     [jsonv2.SemanticError] or [jsontext.SyntacticError].
   449  //
   450  //   - When marshaling, if a user-defined marshal method reports an error,
   451  //     it is always wrapped in a [MarshalerError], even if the error itself
   452  //     is already a [MarshalerError], which may lead to multiple redundant
   453  //     layers of wrapping. In contrast, the v2 semantic is to
   454  //     always wrap an error within [jsonv2.SemanticError]
   455  //     unless it is already a semantic error.
   456  //
   457  //   - When unmarshaling, if a user-defined unmarshal method reports an error,
   458  //     it is never wrapped and reported verbatim. In contrast, the v2 semantic
   459  //     is to always wrap an error within [jsonv2.SemanticError]
   460  //     unless it is already a semantic error.
   461  //
   462  //   - When marshaling or unmarshaling, if a Go struct contains type errors
   463  //     (e.g., conflicting names or malformed field tags), then such errors
   464  //     are ignored and the Go struct uses a best-effort representation.
   465  //     In contrast, the v2 semantic is to report a runtime error.
   466  //
   467  //   - When unmarshaling with [jsonv2.MatchCaseInsensitiveNames], if a JSON
   468  //     object name has a non-exact match with multiple Go struct fields, then
   469  //     an error is not reported and instead the first declared field is used.
   470  //     In contrast, the v2 semantic is to report a runtime error.
   471  //
   472  //   - When unmarshaling, the syntactic structure of the JSON input
   473  //     is fully validated before performing the semantic unmarshaling
   474  //     of the JSON data into the Go value. Practically speaking,
   475  //     this means that JSON input with syntactic errors do not result
   476  //     in any mutations of the target Go value. In contrast, the v2 semantic
   477  //     is to perform a streaming decode and gradually unmarshal the JSON input
   478  //     into the target Go value, which means that the Go value may be
   479  //     partially mutated when a syntactic error is encountered.
   480  //
   481  //   - When unmarshaling, a semantic error does not immediately terminate the
   482  //     unmarshal procedure, but rather evaluation continues.
   483  //     When unmarshal returns, only the first semantic error is reported.
   484  //     In contrast, the v2 semantic is to terminate unmarshal the moment
   485  //     an error is encountered.
   486  //
   487  // This affects either marshaling or unmarshaling.
   488  // The v1 default is true.
   489  func ReportErrorsWithLegacySemantics(v bool) Options {
   490  	if v {
   491  		return jsonflags.ReportErrorsWithLegacySemantics | 1
   492  	} else {
   493  		return jsonflags.ReportErrorsWithLegacySemantics | 0
   494  	}
   495  }
   496  
   497  // StringifyWithLegacySemantics specifies that the `string` tag option
   498  // may stringify bools and string values. It only takes effect on fields
   499  // where the top-level type is a bool, string, numeric kind, or a pointer to
   500  // such a kind. In contrast, the v2 default only allows the `string` tag option
   501  // on Go types that would have otherwise serialized as a JSON number,
   502  // and stringifies the JSON number within a JSON string. In particular,
   503  // the v2 default does not stringify Go bools and strings.
   504  // If [ReportErrorsWithLegacySemantics] is false,
   505  // then incorrect usages of `string` result in a runtime error.
   506  //
   507  // When marshaling, such Go values are serialized as their usual JSON
   508  // representation, but quoted within a JSON string.
   509  // When unmarshaling, such Go values must be deserialized from a JSON string
   510  // containing their usual JSON representation or Go number representation for
   511  // that numeric kind.
   512  // Note that the Go number grammar is a superset of the JSON number grammar.
   513  // A JSON null quoted in a JSON string is a valid substitute for JSON null
   514  // while unmarshaling into a Go value that `string` takes effect on.
   515  // In contrast, the v2 default rejects stringified numbers outside of the
   516  // grammar for a JSON number and also rejects a JSON null quoted in a JSON string.
   517  //
   518  // This affects either marshaling or unmarshaling.
   519  // The v1 default is true.
   520  func StringifyWithLegacySemantics(v bool) Options {
   521  	if v {
   522  		return jsonflags.StringifyWithLegacySemantics | 1
   523  	} else {
   524  		return jsonflags.StringifyWithLegacySemantics | 0
   525  	}
   526  }
   527  
   528  // UnmarshalArrayFromAnyLength specifies that Go arrays can be unmarshaled
   529  // from input JSON arrays of any length. If the JSON array is too short,
   530  // then the remaining Go array elements are zeroed. If the JSON array
   531  // is too long, then the excess JSON array elements are skipped over.
   532  // In contrast, the v2 default expects that Go arrays be unmarshaled
   533  // from input JSON arrays of the exact same length.
   534  //
   535  // This only affects unmarshaling and is ignored when marshaling.
   536  // The v1 default is true.
   537  func UnmarshalArrayFromAnyLength(v bool) Options {
   538  	if v {
   539  		return jsonflags.UnmarshalArrayFromAnyLength | 1
   540  	} else {
   541  		return jsonflags.UnmarshalArrayFromAnyLength | 0
   542  	}
   543  }
   544  
   545  // unmarshalAnyWithRawNumber specifies that unmarshaling a JSON number into
   546  // an empty Go interface should use the Number type instead of a float64.
   547  func unmarshalAnyWithRawNumber(v bool) Options {
   548  	if v {
   549  		return jsonflags.UnmarshalAnyWithRawNumber | 1
   550  	} else {
   551  		return jsonflags.UnmarshalAnyWithRawNumber | 0
   552  	}
   553  }
   554  

View as plain text