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  // JSON names containing commas or quotes, or names identical to "" or "-",
    72  // can be specified using a single-quoted string literal, where the syntax
    73  // is identical to the Go grammar for a double-quoted string literal,
    74  // but instead uses single quotes as the delimiters.
    75  //
    76  // Examples of struct field tags and their meanings:
    77  //
    78  //	// Field appears in JSON as key "myName".
    79  //	Field int `json:"myName"`
    80  //
    81  //	// Field appears in JSON as key "myName" and
    82  //	// the field is omitted from the object if its value is empty,
    83  //	// as defined above.
    84  //	Field int `json:"myName,omitempty"`
    85  //
    86  //	// Field appears in JSON as key "Field" (the default), but
    87  //	// the field is skipped if empty.
    88  //	// Note the leading comma.
    89  //	Field int `json:",omitempty"`
    90  //
    91  //	// Field is ignored by this package.
    92  //	Field int `json:"-"`
    93  //
    94  //	// Field appears in JSON as key "-".
    95  //	Field int `json:"'-'"`
    96  //
    97  // The "omitzero" option specifies that the field should be omitted
    98  // from the encoding if the field has a zero value, according to rules:
    99  //
   100  // 1) If the field type has an "IsZero() bool" method, that will be used to
   101  // determine whether the value is zero.
   102  //
   103  // 2) Otherwise, the value is zero if it is the zero value for its type.
   104  //
   105  // If both "omitempty" and "omitzero" are specified, the field will be omitted
   106  // if the value is either empty or zero (or both).
   107  //
   108  // The "string" option signals that a field is stored as JSON inside a
   109  // JSON-encoded string. It applies only to fields of string, floating point,
   110  // integer, or boolean types. This extra level of encoding is sometimes used
   111  // when communicating with JavaScript programs:
   112  //
   113  //	Int64String int64 `json:",string"`
   114  //
   115  // The key name will be used if it's a non-empty string consisting of
   116  // only Unicode letters, digits, and ASCII punctuation except quotation
   117  // marks, backslash, and comma.
   118  //
   119  // Embedded struct fields are usually marshaled as if their inner exported fields
   120  // were fields in the outer struct, subject to the usual Go visibility rules amended
   121  // as described in the next paragraph.
   122  // An anonymous struct field with a name given in its JSON tag is treated as
   123  // having that name, rather than being anonymous.
   124  // An anonymous struct field of interface type is treated the same as having
   125  // that type as its name, rather than being anonymous.
   126  //
   127  // The Go visibility rules for struct fields are amended for JSON when
   128  // deciding which field to marshal or unmarshal. If there are
   129  // multiple fields at the same level, and that level is the least
   130  // nested (and would therefore be the nesting level selected by the
   131  // usual Go rules), the following extra rules apply:
   132  //
   133  // 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
   134  // even if there are multiple untagged fields that would otherwise conflict.
   135  //
   136  // 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
   137  //
   138  // 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
   139  //
   140  // Handling of anonymous struct fields is new in Go 1.1.
   141  // Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
   142  // an anonymous struct field in both current and earlier versions, give the field
   143  // a JSON tag of "-".
   144  //
   145  // Map values encode as JSON objects. The map's key type must either be a
   146  // string, an integer type, or implement [encoding.TextMarshaler]. The map keys
   147  // are sorted and used as JSON object keys by applying the following rules,
   148  // subject to the UTF-8 coercion described for string values above:
   149  //   - keys of any string type are used directly
   150  //   - keys that implement [encoding.TextMarshaler] are marshaled
   151  //   - integer keys are converted to strings
   152  //
   153  // Pointer values encode as the value pointed to.
   154  // A nil pointer encodes as the null JSON value.
   155  //
   156  // Interface values encode as the value contained in the interface.
   157  // A nil interface value encodes as the null JSON value.
   158  //
   159  // Channel, complex, and function values cannot be encoded in JSON.
   160  // Attempting to encode such a value causes Marshal to return
   161  // an [UnsupportedTypeError].
   162  //
   163  // JSON cannot represent cyclic data structures and Marshal does not
   164  // handle them. Passing cyclic structures to Marshal will result in
   165  // an error.
   166  func Marshal(v any) ([]byte, error) {
   167  	return jsonv2.Marshal(v, DefaultOptionsV1())
   168  }
   169  
   170  // MarshalIndent is like [Marshal] but applies [Indent] to format the output.
   171  // Each JSON element in the output will begin on a new line beginning with prefix
   172  // followed by one or more copies of indent according to the indentation nesting.
   173  func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
   174  	b, err := Marshal(v)
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  	b, err = appendIndent(nil, b, prefix, indent)
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	return b, nil
   183  }
   184  
   185  // Marshaler is the interface implemented by types that
   186  // can marshal themselves into valid JSON.
   187  type Marshaler = jsonv2.Marshaler
   188  
   189  // An UnsupportedTypeError is returned by [Marshal] when attempting
   190  // to encode an unsupported value type.
   191  type UnsupportedTypeError struct {
   192  	Type reflect.Type
   193  }
   194  
   195  func (e *UnsupportedTypeError) Error() string {
   196  	return "json: unsupported type: " + e.Type.String()
   197  }
   198  
   199  // An UnsupportedValueError is returned by [Marshal] when attempting
   200  // to encode an unsupported value.
   201  type UnsupportedValueError struct {
   202  	Value reflect.Value
   203  	Str   string
   204  }
   205  
   206  func (e *UnsupportedValueError) Error() string {
   207  	return "json: unsupported value: " + e.Str
   208  }
   209  
   210  // Before Go 1.2, an InvalidUTF8Error was returned by [Marshal] when
   211  // attempting to encode a string value with invalid UTF-8 sequences.
   212  // As of Go 1.2, [Marshal] instead coerces the string to valid UTF-8 by
   213  // replacing invalid bytes with the Unicode replacement rune U+FFFD.
   214  //
   215  // Deprecated: No longer used; kept for compatibility.
   216  type InvalidUTF8Error struct {
   217  	S string // the whole string value that caused the error
   218  }
   219  
   220  func (e *InvalidUTF8Error) Error() string {
   221  	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
   222  }
   223  
   224  // A MarshalerError represents an error from calling a
   225  // [Marshaler.MarshalJSON] or [encoding.TextMarshaler.MarshalText] method.
   226  type MarshalerError struct {
   227  	Type       reflect.Type
   228  	Err        error
   229  	sourceFunc string
   230  }
   231  
   232  func (e *MarshalerError) Error() string {
   233  	srcFunc := e.sourceFunc
   234  	if srcFunc == "" {
   235  		srcFunc = "MarshalJSON"
   236  	}
   237  	return "json: error calling " + srcFunc +
   238  		" for type " + e.Type.String() +
   239  		": " + e.Err.Error()
   240  }
   241  
   242  // Unwrap returns the underlying error.
   243  func (e *MarshalerError) Unwrap() error { return e.Err }
   244  

View as plain text