// Unmarshal parses the JSON-encoded data and stores the result // in the value pointed to by v. If v is nil or not a pointer, // Unmarshal returns an [InvalidUnmarshalError]. // // Unmarshal uses the inverse of the encodings that // [Marshal] uses, allocating maps, slices, and pointers as necessary, // with the following additional rules: // // To unmarshal JSON into a pointer, Unmarshal first handles the case of // the JSON being the JSON literal null. In that case, Unmarshal sets // the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into // the value pointed at by the pointer. If the pointer is nil, Unmarshal // allocates a new value for it to point to. // // To unmarshal JSON into a value implementing [Unmarshaler], // Unmarshal calls that value's [Unmarshaler.UnmarshalJSON] method, including // when the input is a JSON null. // Otherwise, if the value implements [encoding.TextUnmarshaler] // and the input is a JSON quoted string, Unmarshal calls // [encoding.TextUnmarshaler.UnmarshalText] with the unquoted form of the string. // // To unmarshal JSON into a struct, Unmarshal matches incoming object // keys to the keys used by [Marshal] (either the struct field name or its tag), // preferring an exact match but also accepting a case-insensitive match. By // default, object keys which don't have a corresponding struct field are // ignored (see [Decoder.DisallowUnknownFields] for an alternative). // // To unmarshal JSON into an interface value, // Unmarshal stores one of these in the interface value: // // - bool, for JSON booleans // - float64, for JSON numbers // - string, for JSON strings // - []interface{}, for JSON arrays // - map[string]interface{}, for JSON objects // - nil for JSON null // // To unmarshal a JSON array into a slice, Unmarshal resets the slice length // to zero and then appends each element to the slice. // As a special case, to unmarshal an empty JSON array into a slice, // Unmarshal replaces the slice with a new empty slice. // // To unmarshal a JSON array into a Go array, Unmarshal decodes // JSON array elements into corresponding Go array elements. // If the Go array is smaller than the JSON array, // the additional JSON array elements are discarded. // If the JSON array is smaller than the Go array, // the additional Go array elements are set to zero values. // // To unmarshal a JSON object into a map, Unmarshal first establishes a map to // use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal // reuses the existing map, keeping existing entries. Unmarshal then stores // key-value pairs from the JSON object into the map. The map's key type must // either be any string type, an integer, or implement [encoding.TextUnmarshaler]. // // If the JSON-encoded data contain a syntax error, Unmarshal returns a [SyntaxError]. // // If a JSON value is not appropriate for a given target type, // or if a JSON number overflows the target type, Unmarshal // skips that field and completes the unmarshaling as best it can. // If no more serious errors are encountered, Unmarshal returns // an [UnmarshalTypeError] describing the earliest such error. In any // case, it's not guaranteed that all the remaining fields following // the problematic one will be unmarshaled into the target object. // // The JSON null value unmarshals into an interface, map, pointer, or slice // by setting that Go value to nil. Because null is often used in JSON to mean // “not present,” unmarshaling a JSON null into any other Go type has no effect // on the value and produces no error. // // When unmarshaling quoted strings, invalid UTF-8 or // invalid UTF-16 surrogate pairs are not treated as an error. // Instead, they are replaced by the Unicode replacement // character U+FFFD. func Unmarshal(data []byte, v any, opts ...UnmarshalOpt) error { … } type Unmarshaler … func (d *decodeState) unmarshal(v any) error { … } type errorContext … type decodeState … // readIndex returns the position of the last byte read. func (d *decodeState) readIndex() int { … } const phasePanicMsg … func (d *decodeState) init(data []byte) *decodeState { … } // saveError saves the first err it is called with, // for reporting at the end of the unmarshal. func (d *decodeState) saveError(err error) { … } // addErrorContext returns a new error enhanced with information from d.errorContext func (d *decodeState) addErrorContext(err error) error { … } // skip scans to the end of what was started. func (d *decodeState) skip() { … } // scanNext processes the byte at d.data[d.off]. func (d *decodeState) scanNext() { … } // scanWhile processes bytes in d.data[d.off:] until it // receives a scan code not equal to op. func (d *decodeState) scanWhile(op int) { … } // rescanLiteral is similar to scanWhile(scanContinue), but it specialises the // common case where we're decoding a literal. The decoder scans the input // twice, once for syntax errors and to check the length of the value, and the // second to perform the decoding. // // Only in the second step do we use decodeState to tokenize literals, so we // know there aren't any syntax errors. We can take advantage of that knowledge, // and scan a literal's bytes much more quickly. func (d *decodeState) rescanLiteral() { … } // value consumes a JSON value from d.data[d.off-1:], decoding into v, and // reads the following byte ahead. If v is invalid, the value is discarded. // The first byte of the value has been read already. func (d *decodeState) value(v reflect.Value) error { … } type unquotedValue … // valueQuoted is like value but decodes a // quoted string literal or literal null into an interface value. // If it finds anything other than a quoted string literal or null, // valueQuoted returns unquotedValue{}. func (d *decodeState) valueQuoted() any { … } // indirect walks down v allocating pointers as needed, // until it gets to a non-pointer. // If it encounters an Unmarshaler, indirect stops and returns that. // If decodingNull is true, indirect stops at the first settable pointer so it // can be set to nil. func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { … } // array consumes an array from d.data[d.off-1:], decoding into v. // The first byte of the array ('[') has been read already. func (d *decodeState) array(v reflect.Value) error { … } var nullLiteral … var textUnmarshalerType … // object consumes an object from d.data[d.off-1:], decoding into v. // The first byte ('{') of the object has been read already. func (d *decodeState) object(v reflect.Value) error { … } // convertNumber converts the number literal s to a float64 or a Number // depending on the setting of d.useNumber. func (d *decodeState) convertNumber(s string) (any, error) { … } var numberType … // literalStore decodes a literal stored in item into v. // // fromQuoted indicates whether this literal came from unwrapping a // string from the ",string" struct tag option. this is used only to // produce more helpful error messages. func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error { … } // valueInterface is like value but returns interface{} func (d *decodeState) valueInterface() (val any) { … } // arrayInterface is like array but returns []interface{}. func (d *decodeState) arrayInterface() []any { … } // objectInterface is like object but returns map[string]interface{}. func (d *decodeState) objectInterface() map[string]any { … } // literalInterface consumes and returns a literal from d.data[d.off-1:] and // it reads the following byte ahead. The first byte of the literal has been // read already (that's how the caller knows it's a literal). func (d *decodeState) literalInterface() any { … } // getu4 decodes \uXXXX from the beginning of s, returning the hex value, // or it returns -1. func getu4(s []byte) rune { … } // unquote converts a quoted JSON string literal s into an actual string t. // The rules are different than for Go, so cannot use strconv.Unquote. func unquote(s []byte) (t string, ok bool) { … } func unquoteBytes(s []byte) (t []byte, ok bool) { … }