Source file src/encoding/json/v2_encode.go

     1  // Copyright 2010 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 implements encoding and decoding of JSON as defined in
     8  // RFC 7159. The mapping between JSON and Go values is described
     9  // in the documentation for the Marshal and Unmarshal functions.
    10  //
    11  // See "JSON and Go" for an introduction to this package:
    12  // https://golang.org/doc/articles/json_and_go.html
    13  //
    14  // # Security Considerations
    15  //
    16  // See the "Security Considerations" section in [encoding/json/v2].
    17  //
    18  // For historical reasons, the default behavior of v1 [encoding/json]
    19  // unfortunately operates with less secure defaults.
    20  // New usages of JSON in Go are encouraged to use [encoding/json/v2] instead.
    21  package json
    22  
    23  import (
    24  	"reflect"
    25  	"strconv"
    26  
    27  	jsonv2 "encoding/json/v2"
    28  )
    29  
    30  // Marshal returns the JSON encoding of v.
    31  //
    32  // Marshal traverses the value v recursively.
    33  // If an encountered value implements [Marshaler]
    34  // and is not a nil pointer, Marshal calls [Marshaler.MarshalJSON]
    35  // to produce JSON. If no [Marshaler.MarshalJSON] method is present but the
    36  // value implements [encoding.TextMarshaler] instead, Marshal calls
    37  // [encoding.TextMarshaler.MarshalText] and encodes the result as a JSON string.
    38  // The nil pointer exception is not strictly necessary
    39  // but mimics a similar, necessary exception in the behavior of
    40  // [Unmarshaler.UnmarshalJSON].
    41  //
    42  // Otherwise, Marshal uses the following type-dependent default encodings:
    43  //
    44  // Boolean values encode as JSON booleans.
    45  //
    46  // Floating point, integer, and [Number] values encode as JSON numbers.
    47  // NaN and +/-Inf values will return an [UnsupportedValueError].
    48  //
    49  // String values encode as JSON strings coerced to valid UTF-8,
    50  // replacing invalid bytes with the Unicode replacement rune.
    51  // So that the JSON will be safe to embed inside HTML <script> tags,
    52  // the string is encoded using [HTMLEscape],
    53  // which replaces "<", ">", "&", U+2028, and U+2029 are escaped
    54  // to "\u003c","\u003e", "\u0026", "\u2028", and "\u2029".
    55  // This replacement can be disabled when using an [Encoder],
    56  // by calling [Encoder.SetEscapeHTML](false).
    57  //
    58  // Array and slice values encode as JSON arrays, except that
    59  // []byte encodes as a base64-encoded string, and a nil slice
    60  // encodes as the null JSON value.
    61  //
    62  // Struct values encode as JSON objects.
    63  // Each exported struct field becomes a member of the object, using the
    64  // field name as the object key, unless the field is omitted for one of the
    65  // reasons given below.
    66  //
    67  // The encoding of each struct field can be customized by the format string
    68  // stored under the "json" key in the struct field's tag.
    69  // The format string gives the name of the field, possibly followed by a
    70  // comma-separated list of options. The name may be empty in order to
    71  // specify options without overriding the default field name.
    72  //
    73  // The "omitempty" option specifies that the field should be omitted
    74  // from the encoding if the field has an empty value, defined as
    75  // false, 0, a nil pointer, a nil interface value, and any array,
    76  // slice, map, or string of length zero.
    77  //
    78  // As a special case, if the field tag is "-", the field is always omitted.
    79  // JSON names containing commas or quotes, or names identical to "" or "-",
    80  // can be specified using a single-quoted string literal, where the syntax
    81  // is identical to the Go grammar for a double-quoted string literal,
    82  // but instead uses single quotes as the delimiters.
    83  //
    84  // Examples of struct field tags and their meanings:
    85  //
    86  //	// Field appears in JSON as key "myName".
    87  //	Field int `json:"myName"`
    88  //
    89  //	// Field appears in JSON as key "myName" and
    90  //	// the field is omitted from the object if its value is empty,
    91  //	// as defined above.
    92  //	Field int `json:"myName,omitempty"`
    93  //
    94  //	// Field appears in JSON as key "Field" (the default), but
    95  //	// the field is skipped if empty.
    96  //	// Note the leading comma.
    97  //	Field int `json:",omitempty"`
    98  //
    99  //	// Field is ignored by this package.
   100  //	Field int `json:"-"`
   101  //
   102  //	// Field appears in JSON as key "-".
   103  //	Field int `json:"'-'"`
   104  //
   105  // The "omitzero" option specifies that the field should be omitted
   106  // from the encoding if the field has a zero value, according to rules:
   107  //
   108  // 1) If the field type has an "IsZero() bool" method, that will be used to
   109  // determine whether the value is zero.
   110  //
   111  // 2) Otherwise, the value is zero if it is the zero value for its type.
   112  //
   113  // If both "omitempty" and "omitzero" are specified, the field will be omitted
   114  // if the value is either empty or zero (or both).
   115  //
   116  // The "string" option signals that a field is stored as JSON inside a
   117  // JSON-encoded string. It applies only to fields of string, floating point,
   118  // integer, or boolean types. This extra level of encoding is sometimes used
   119  // when communicating with JavaScript programs:
   120  //
   121  //	Int64String int64 `json:",string"`
   122  //
   123  // The key name will be used if it's a non-empty string consisting of
   124  // only Unicode letters, digits, and ASCII punctuation except quotation
   125  // marks, backslash, and comma.
   126  //
   127  // Embedded struct fields are usually marshaled as if their inner exported fields
   128  // were fields in the outer struct, subject to the usual Go visibility rules amended
   129  // as described in the next paragraph.
   130  // An anonymous struct field with a name given in its JSON tag is treated as
   131  // having that name, rather than being anonymous.
   132  // An anonymous struct field of interface type is treated the same as having
   133  // that type as its name, rather than being anonymous.
   134  //
   135  // The Go visibility rules for struct fields are amended for JSON when
   136  // deciding which field to marshal or unmarshal. If there are
   137  // multiple fields at the same level, and that level is the least
   138  // nested (and would therefore be the nesting level selected by the
   139  // usual Go rules), the following extra rules apply:
   140  //
   141  // 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
   142  // even if there are multiple untagged fields that would otherwise conflict.
   143  //
   144  // 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
   145  //
   146  // 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
   147  //
   148  // Handling of anonymous struct fields is new in Go 1.1.
   149  // Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
   150  // an anonymous struct field in both current and earlier versions, give the field
   151  // a JSON tag of "-".
   152  //
   153  // Map values encode as JSON objects. The map's key type must either be a
   154  // string, an integer type, or implement [encoding.TextMarshaler]. The map keys
   155  // are sorted and used as JSON object keys by applying the following rules,
   156  // subject to the UTF-8 coercion described for string values above:
   157  //   - keys of any string type are used directly
   158  //   - keys that implement [encoding.TextMarshaler] are marshaled
   159  //   - integer keys are converted to strings
   160  //
   161  // Pointer values encode as the value pointed to.
   162  // A nil pointer encodes as the null JSON value.
   163  //
   164  // Interface values encode as the value contained in the interface.
   165  // A nil interface value encodes as the null JSON value.
   166  //
   167  // Channel, complex, and function values cannot be encoded in JSON.
   168  // Attempting to encode such a value causes Marshal to return
   169  // an [UnsupportedTypeError].
   170  //
   171  // JSON cannot represent cyclic data structures and Marshal does not
   172  // handle them. Passing cyclic structures to Marshal will result in
   173  // an error.
   174  func Marshal(v any) ([]byte, error) {
   175  	return jsonv2.Marshal(v, DefaultOptionsV1())
   176  }
   177  
   178  // MarshalIndent is like [Marshal] but applies [Indent] to format the output.
   179  // Each JSON element in the output will begin on a new line beginning with prefix
   180  // followed by one or more copies of indent according to the indentation nesting.
   181  func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
   182  	b, err := Marshal(v)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  	b, err = appendIndent(nil, b, prefix, indent)
   187  	if err != nil {
   188  		return nil, err
   189  	}
   190  	return b, nil
   191  }
   192  
   193  // Marshaler is the interface implemented by types that
   194  // can marshal themselves into valid JSON.
   195  type Marshaler = jsonv2.Marshaler
   196  
   197  // An UnsupportedTypeError is returned by [Marshal] when attempting
   198  // to encode an unsupported value type.
   199  type UnsupportedTypeError struct {
   200  	Type reflect.Type
   201  }
   202  
   203  func (e *UnsupportedTypeError) Error() string {
   204  	return "json: unsupported type: " + e.Type.String()
   205  }
   206  
   207  // An UnsupportedValueError is returned by [Marshal] when attempting
   208  // to encode an unsupported value.
   209  type UnsupportedValueError struct {
   210  	Value reflect.Value
   211  	Str   string
   212  }
   213  
   214  func (e *UnsupportedValueError) Error() string {
   215  	return "json: unsupported value: " + e.Str
   216  }
   217  
   218  // Before Go 1.2, an InvalidUTF8Error was returned by [Marshal] when
   219  // attempting to encode a string value with invalid UTF-8 sequences.
   220  // As of Go 1.2, [Marshal] instead coerces the string to valid UTF-8 by
   221  // replacing invalid bytes with the Unicode replacement rune U+FFFD.
   222  //
   223  // Deprecated: No longer used; kept for compatibility.
   224  type InvalidUTF8Error struct {
   225  	S string // the whole string value that caused the error
   226  }
   227  
   228  func (e *InvalidUTF8Error) Error() string {
   229  	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
   230  }
   231  
   232  // A MarshalerError represents an error from calling a
   233  // [Marshaler.MarshalJSON] or [encoding.TextMarshaler.MarshalText] method.
   234  type MarshalerError struct {
   235  	Type       reflect.Type
   236  	Err        error
   237  	sourceFunc string
   238  }
   239  
   240  func (e *MarshalerError) Error() string {
   241  	srcFunc := e.sourceFunc
   242  	if srcFunc == "" {
   243  		srcFunc = "MarshalJSON"
   244  	}
   245  	return "json: error calling " + srcFunc +
   246  		" for type " + e.Type.String() +
   247  		": " + e.Err.Error()
   248  }
   249  
   250  // Unwrap returns the underlying error.
   251  func (e *MarshalerError) Unwrap() error { return e.Err }
   252  

View as plain text