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

View as plain text