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