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  	s := "json: cannot unmarshal"
   121  	if e.Value != "" {
   122  		s += " JSON " + e.Value
   123  	}
   124  	s += " into"
   125  	var preposition string
   126  	if e.Field != "" {
   127  		s += " " + e.Struct + "." + e.Field
   128  		preposition = " of"
   129  	}
   130  	if e.Type != nil {
   131  		s += preposition
   132  		s += " Go type " + e.Type.String()
   133  	}
   134  	if e.Err != nil {
   135  		s += ": " + e.Err.Error()
   136  	}
   137  	return s
   138  }
   139  
   140  func (e *UnmarshalTypeError) Unwrap() error {
   141  	return e.Err
   142  }
   143  
   144  // An UnmarshalFieldError describes a JSON object key that
   145  // led to an unexported (and therefore unwritable) struct field.
   146  //
   147  // Deprecated: No longer used; kept for compatibility.
   148  type UnmarshalFieldError struct {
   149  	Key   string
   150  	Type  reflect.Type
   151  	Field reflect.StructField
   152  }
   153  
   154  func (e *UnmarshalFieldError) Error() string {
   155  	return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
   156  }
   157  
   158  // An InvalidUnmarshalError describes an invalid argument passed to [Unmarshal].
   159  // (The argument to [Unmarshal] must be a non-nil pointer.)
   160  type InvalidUnmarshalError struct {
   161  	Type reflect.Type
   162  }
   163  
   164  func (e *InvalidUnmarshalError) Error() string {
   165  	if e.Type == nil {
   166  		return "json: Unmarshal(nil)"
   167  	}
   168  
   169  	if e.Type.Kind() != reflect.Pointer {
   170  		return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
   171  	}
   172  	return "json: Unmarshal(nil " + e.Type.String() + ")"
   173  }
   174  
   175  // A Number represents a JSON number literal.
   176  type Number string
   177  
   178  // String returns the literal text of the number.
   179  func (n Number) String() string { return string(n) }
   180  
   181  // Float64 returns the number as a float64.
   182  func (n Number) Float64() (float64, error) {
   183  	return strconv.ParseFloat(string(n), 64)
   184  }
   185  
   186  // Int64 returns the number as an int64.
   187  func (n Number) Int64() (int64, error) {
   188  	return strconv.ParseInt(string(n), 10, 64)
   189  }
   190  
   191  var numberType = reflect.TypeFor[Number]()
   192  
   193  // MarshalJSONTo implements [jsonv2.MarshalerTo].
   194  func (n Number) MarshalJSONTo(enc *jsontext.Encoder) error {
   195  	opts := enc.Options()
   196  	stringify, _ := jsonv2.GetOption(opts, jsonv2.StringifyNumbers)
   197  	if k, n := enc.StackIndex(enc.StackDepth()); k == '{' && n%2 == 0 {
   198  		stringify = true // expecting a JSON object name
   199  	}
   200  	n = cmp.Or(n, "0")
   201  	var num []byte
   202  	val := enc.UnusedBuffer()
   203  	if stringify {
   204  		val = append(val, '"')
   205  		val = append(val, n...)
   206  		val = append(val, '"')
   207  		num = val[len(`"`) : len(val)-len(`"`)]
   208  	} else {
   209  		val = append(val, n...)
   210  		num = val
   211  	}
   212  	if n, err := jsonwire.ConsumeNumber(num); n != len(num) || err != nil {
   213  		return fmt.Errorf("cannot parse %q as JSON number: %w", val, strconv.ErrSyntax)
   214  	}
   215  	return enc.WriteValue(val)
   216  }
   217  
   218  // UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
   219  func (n *Number) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
   220  	opts := dec.Options()
   221  	stringify, _ := jsonv2.GetOption(opts, jsonv2.StringifyNumbers)
   222  	if k, n := dec.StackIndex(dec.StackDepth()); k == '{' && n%2 == 0 {
   223  		stringify = true // expecting a JSON object name
   224  	}
   225  	val, err := dec.ReadValue()
   226  	if err != nil {
   227  		return err
   228  	}
   229  	val0 := val
   230  	k := val.Kind()
   231  	switch k {
   232  	case 'n':
   233  		if legacy, _ := jsonv2.GetOption(opts, MergeWithLegacySemantics); !legacy {
   234  			*n = ""
   235  		}
   236  		return nil
   237  	case '"':
   238  		verbatim := jsonwire.ConsumeSimpleString(val) == len(val)
   239  		val = jsonwire.UnquoteMayCopy(val, verbatim)
   240  		if n, err := jsonwire.ConsumeNumber(val); n != len(val) || err != nil {
   241  			return &jsonv2.SemanticError{JSONKind: val0.Kind(), JSONValue: val0.Clone(), GoType: numberType, Err: strconv.ErrSyntax}
   242  		}
   243  		*n = Number(val)
   244  		return nil
   245  	case '0':
   246  		if stringify {
   247  			break
   248  		}
   249  		*n = Number(val)
   250  		return nil
   251  	}
   252  	return &jsonv2.SemanticError{JSONKind: k, GoType: numberType}
   253  }
   254  

View as plain text