Source file src/encoding/json/v2_decode.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  // Represents JSON data structure using native Go types: booleans, floats,
     8  // strings, arrays, and maps.
     9  
    10  package json
    11  
    12  import (
    13  	"cmp"
    14  	"fmt"
    15  	"reflect"
    16  	"strconv"
    17  
    18  	"encoding/json/internal/jsonwire"
    19  	"encoding/json/jsontext"
    20  	jsonv2 "encoding/json/v2"
    21  )
    22  
    23  // Unmarshal parses the JSON-encoded data and stores the result
    24  // in the value pointed to by v. If v is nil or not a pointer,
    25  // Unmarshal returns an [InvalidUnmarshalError].
    26  //
    27  // Unmarshal uses the inverse of the encodings that
    28  // [Marshal] uses, allocating maps, slices, and pointers as necessary,
    29  // with the following additional rules:
    30  //
    31  // To unmarshal JSON into a pointer, Unmarshal first handles the case of
    32  // the JSON being the JSON literal null. In that case, Unmarshal sets
    33  // the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
    34  // the value pointed at by the pointer. If the pointer is nil, Unmarshal
    35  // allocates a new value for it to point to.
    36  //
    37  // To unmarshal JSON into a value implementing [Unmarshaler],
    38  // Unmarshal calls that value's [Unmarshaler.UnmarshalJSON] method, including
    39  // when the input is a JSON null.
    40  // Otherwise, if the value implements [encoding.TextUnmarshaler]
    41  // and the input is a JSON quoted string, Unmarshal calls
    42  // [encoding.TextUnmarshaler.UnmarshalText] with the unquoted form of the string.
    43  //
    44  // To unmarshal JSON into a struct, Unmarshal matches incoming object
    45  // keys to the keys used by [Marshal] (either the struct field name or its tag),
    46  // preferring an exact match but also accepting a case-insensitive match. By
    47  // default, object keys which don't have a corresponding struct field are
    48  // ignored (see [Decoder.DisallowUnknownFields] for an alternative).
    49  //
    50  // To unmarshal JSON into an interface value,
    51  // Unmarshal stores one of these in the interface value:
    52  //
    53  //   - bool, for JSON booleans
    54  //   - float64, for JSON numbers
    55  //   - string, for JSON strings
    56  //   - []any, for JSON arrays
    57  //   - map[string]any, for JSON objects
    58  //   - nil for JSON null
    59  //
    60  // To unmarshal a JSON array into a slice, Unmarshal resets the slice length
    61  // to zero and then appends each element to the slice.
    62  // As a special case, to unmarshal an empty JSON array into a slice,
    63  // Unmarshal replaces the slice with a new empty slice.
    64  //
    65  // To unmarshal a JSON array into a Go array, Unmarshal decodes
    66  // JSON array elements into corresponding Go array elements.
    67  // If the Go array is smaller than the JSON array,
    68  // the additional JSON array elements are discarded.
    69  // If the JSON array is smaller than the Go array,
    70  // the additional Go array elements are set to zero values.
    71  //
    72  // To unmarshal a JSON object into a map, Unmarshal first establishes a map to
    73  // use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
    74  // reuses the existing map, keeping existing entries. Unmarshal then stores
    75  // key-value pairs from the JSON object into the map. The map's key type must
    76  // either be any string type, an integer, or implement [encoding.TextUnmarshaler].
    77  //
    78  // If the JSON-encoded data contain a syntax error, Unmarshal returns a [SyntaxError].
    79  //
    80  // If a JSON value is not appropriate for a given target type,
    81  // or if a JSON number overflows the target type, Unmarshal
    82  // skips that field and completes the unmarshaling as best it can.
    83  // If no more serious errors are encountered, Unmarshal returns
    84  // an [UnmarshalTypeError] describing the earliest such error. In any
    85  // case, it's not guaranteed that all the remaining fields following
    86  // the problematic one will be unmarshaled into the target object.
    87  //
    88  // The JSON null value unmarshals into an interface, map, pointer, or slice
    89  // by setting that Go value to nil. Because null is often used in JSON to mean
    90  // “not present,” unmarshaling a JSON null into any other Go type has no effect
    91  // on the value and produces no error.
    92  //
    93  // When unmarshaling quoted strings, invalid UTF-8 or
    94  // invalid UTF-16 surrogate pairs are not treated as an error.
    95  // Instead, they are replaced by the Unicode replacement
    96  // character U+FFFD.
    97  func Unmarshal(data []byte, v any) error {
    98  	return jsonv2.Unmarshal(data, v, DefaultOptionsV1())
    99  }
   100  
   101  // Unmarshaler is the interface implemented by types
   102  // that can unmarshal a JSON description of themselves.
   103  // The input can be assumed to be a valid encoding of
   104  // a JSON value. UnmarshalJSON must copy the JSON data
   105  // if it wishes to retain the data after returning.
   106  type Unmarshaler = jsonv2.Unmarshaler
   107  
   108  // An UnmarshalTypeError describes a JSON value that was
   109  // not appropriate for a value of a specific Go type.
   110  type UnmarshalTypeError struct {
   111  	Value  string       // description of JSON value - "bool", "array", "number -5"
   112  	Type   reflect.Type // type of Go value it could not be assigned to
   113  	Offset int64        // error occurred after reading Offset bytes
   114  	Struct string       // name of the root type containing the field
   115  	Field  string       // the full path from root node to the value
   116  	Err    error        // may be nil
   117  }
   118  
   119  func (e *UnmarshalTypeError) Error() string {
   120  	var s string
   121  	if e.Struct != "" || e.Field != "" {
   122  		s = "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String()
   123  	} else {
   124  		s = "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
   125  	}
   126  	if e.Err != nil {
   127  		s += ": " + e.Err.Error()
   128  	}
   129  	return s
   130  }
   131  
   132  func (e *UnmarshalTypeError) Unwrap() error {
   133  	return e.Err
   134  }
   135  
   136  // An UnmarshalFieldError describes a JSON object key that
   137  // led to an unexported (and therefore unwritable) struct field.
   138  //
   139  // Deprecated: No longer used; kept for compatibility.
   140  type UnmarshalFieldError struct {
   141  	Key   string
   142  	Type  reflect.Type
   143  	Field reflect.StructField
   144  }
   145  
   146  func (e *UnmarshalFieldError) Error() string {
   147  	return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
   148  }
   149  
   150  // An InvalidUnmarshalError describes an invalid argument passed to [Unmarshal].
   151  // (The argument to [Unmarshal] must be a non-nil pointer.)
   152  type InvalidUnmarshalError struct {
   153  	Type reflect.Type
   154  }
   155  
   156  func (e *InvalidUnmarshalError) Error() string {
   157  	if e.Type == nil {
   158  		return "json: Unmarshal(nil)"
   159  	}
   160  
   161  	if e.Type.Kind() != reflect.Pointer {
   162  		return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
   163  	}
   164  	return "json: Unmarshal(nil " + e.Type.String() + ")"
   165  }
   166  
   167  // A Number represents a JSON number literal.
   168  type Number string
   169  
   170  // String returns the literal text of the number.
   171  func (n Number) String() string { return string(n) }
   172  
   173  // Float64 returns the number as a float64.
   174  func (n Number) Float64() (float64, error) {
   175  	return strconv.ParseFloat(string(n), 64)
   176  }
   177  
   178  // Int64 returns the number as an int64.
   179  func (n Number) Int64() (int64, error) {
   180  	return strconv.ParseInt(string(n), 10, 64)
   181  }
   182  
   183  var numberType = reflect.TypeFor[Number]()
   184  
   185  // MarshalJSONTo implements [jsonv2.MarshalerTo].
   186  func (n Number) MarshalJSONTo(enc *jsontext.Encoder) error {
   187  	opts := enc.Options()
   188  	stringify, _ := jsonv2.GetOption(opts, jsonv2.StringifyNumbers)
   189  	if k, n := enc.StackIndex(enc.StackDepth()); k == '{' && n%2 == 0 {
   190  		stringify = true // expecting a JSON object name
   191  	}
   192  	n = cmp.Or(n, "0")
   193  	var num []byte
   194  	val := enc.AvailableBuffer()
   195  	if stringify {
   196  		val = append(val, '"')
   197  		val = append(val, n...)
   198  		val = append(val, '"')
   199  		num = val[len(`"`) : len(val)-len(`"`)]
   200  	} else {
   201  		val = append(val, n...)
   202  		num = val
   203  	}
   204  	if n, err := jsonwire.ConsumeNumber(num); n != len(num) || err != nil {
   205  		return fmt.Errorf("cannot parse %q as JSON number: %w", val, strconv.ErrSyntax)
   206  	}
   207  	return enc.WriteValue(val)
   208  }
   209  
   210  // UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
   211  func (n *Number) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
   212  	opts := dec.Options()
   213  	stringify, _ := jsonv2.GetOption(opts, jsonv2.StringifyNumbers)
   214  	if k, n := dec.StackIndex(dec.StackDepth()); k == '{' && n%2 == 0 {
   215  		stringify = true // expecting a JSON object name
   216  	}
   217  	val, err := dec.ReadValue()
   218  	if err != nil {
   219  		return err
   220  	}
   221  	val0 := val
   222  	k := val.Kind()
   223  	switch k {
   224  	case 'n':
   225  		if legacy, _ := jsonv2.GetOption(opts, MergeWithLegacySemantics); !legacy {
   226  			*n = ""
   227  		}
   228  		return nil
   229  	case '"':
   230  		verbatim := jsonwire.ConsumeSimpleString(val) == len(val)
   231  		val = jsonwire.UnquoteMayCopy(val, verbatim)
   232  		if n, err := jsonwire.ConsumeNumber(val); n != len(val) || err != nil {
   233  			return &jsonv2.SemanticError{JSONKind: val0.Kind(), JSONValue: val0.Clone(), GoType: numberType, Err: strconv.ErrSyntax}
   234  		}
   235  		*n = Number(val)
   236  		return nil
   237  	case '0':
   238  		if stringify {
   239  			break
   240  		}
   241  		*n = Number(val)
   242  		return nil
   243  	}
   244  	return &jsonv2.SemanticError{JSONKind: k, GoType: numberType}
   245  }
   246  

View as plain text