Help us shape the future of Go! Take the 2026 Go Developer Survey

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

View as plain text