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