Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
v2_decode.go260 linesDownload Raw Back to json
1// Copyright 2010 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4 5//go:build goexperiment.jsonv26 7// Represents JSON data structure using native Go types: booleans, floats,8// strings, arrays, and maps.9 10package json11 12import (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 result25// 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 that29// [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 of33// the JSON being the JSON literal null. In that case, Unmarshal sets34// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into35// the value pointed at by the pointer. If the pointer is nil, Unmarshal36// allocates a new value for it to point to.37//38// To unmarshal JSON into a value implementing [Unmarshaler],39// Unmarshal calls that value's [Unmarshaler.UnmarshalJSON] method, including40// when the input is a JSON null.41// Otherwise, if the value implements [encoding.TextUnmarshaler]42// and the input is a JSON quoted string, Unmarshal calls43// [encoding.TextUnmarshaler.UnmarshalText] with the unquoted form of the string.44//45// To unmarshal JSON into a struct, Unmarshal matches incoming object46// keys to the keys used by [Marshal] (either the struct field name or its tag),47// preferring an exact match but also accepting a case-insensitive match. By48// default, object keys which don't have a corresponding struct field are49// ignored (see [Decoder.DisallowUnknownFields] for an alternative).50//51// To unmarshal JSON into an interface value,52// Unmarshal stores one of these in the interface value:53//54//   - bool, for JSON booleans55//   - float64, for JSON numbers56//   - string, for JSON strings57//   - []any, for JSON arrays58//   - map[string]any, for JSON objects59//   - nil for JSON null60//61// To unmarshal a JSON array into a slice, Unmarshal resets the slice length62// to zero and then appends each element to the slice.63// As a special case, to unmarshal an empty JSON array into a slice,64// Unmarshal replaces the slice with a new empty slice.65//66// To unmarshal a JSON array into a Go array, Unmarshal decodes67// JSON array elements into corresponding Go array elements.68// If the Go array is smaller than the JSON array,69// the additional JSON array elements are discarded.70// If the JSON array is smaller than the Go array,71// the additional Go array elements are set to zero values.72//73// To unmarshal a JSON object into a map, Unmarshal first establishes a map to74// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal75// reuses the existing map, keeping existing entries. Unmarshal then stores76// key-value pairs from the JSON object into the map. The map's key type must77// either be any string type, an integer, or implement [encoding.TextUnmarshaler].78//79// If the JSON-encoded data contain a syntax error, Unmarshal returns a [SyntaxError].80//81// If a JSON value is not appropriate for a given target type,82// or if a JSON number overflows the target type, Unmarshal83// skips that field and completes the unmarshaling as best it can.84// If no more serious errors are encountered, Unmarshal returns85// an [UnmarshalTypeError] describing the earliest such error. In any86// case, it's not guaranteed that all the remaining fields following87// the problematic one will be unmarshaled into the target object.88//89// The JSON null value unmarshals into an interface, map, pointer, or slice90// by setting that Go value to nil. Because null is often used in JSON to mean91// “not present,” unmarshaling a JSON null into any other Go type has no effect92// on the value and produces no error.93//94// When unmarshaling quoted strings, invalid UTF-8 or95// invalid UTF-16 surrogate pairs are not treated as an error.96// Instead, they are replaced by the Unicode replacement97// character U+FFFD.98func Unmarshal(data []byte, v any) error {99	return jsonv2.Unmarshal(data, v, DefaultOptionsV1())100}101 102// Unmarshaler is the interface implemented by types103// that can unmarshal a JSON description of themselves.104// The input can be assumed to be a valid encoding of105// a JSON value. UnmarshalJSON must copy the JSON data106// if it wishes to retain the data after returning.107type Unmarshaler = jsonv2.Unmarshaler108 109// An UnmarshalTypeError describes a JSON value that was110// not appropriate for a value of a specific Go type.111type UnmarshalTypeError struct {112	Value  string       // description of JSON value - "bool", "array", "number -5"113	Type   reflect.Type // type of Go value it could not be assigned to114	Offset int64        // error occurred after reading Offset bytes115	Struct string       // name of the root type containing the field116	Field  string       // the full path from root node to the value117	Err    error        // may be nil118}119 120func (e *UnmarshalTypeError) Error() string {121	var s string122	if e.Struct != "" || e.Field != "" {123		// The design of UnmarshalTypeError overly assumes a struct-based124		// Go representation for the JSON value.125		// The logic in jsontext represents paths using a JSON Pointer,126		// which is agnostic to the Go type system.127		// Trying to convert a JSON Pointer into a UnmarshalTypeError.Field128		// is difficult. As a heuristic, if the last path token looks like129		// an index into a JSON array (e.g., ".foo.bar.0"),130		// avoid the phrase "Go struct field ".131		intoWhat := "Go struct field "132		i := strings.LastIndexByte(e.Field, '.') + len(".")133		if len(e.Field[i:]) > 0 && strings.TrimRight(e.Field[i:], "0123456789") == "" {134			intoWhat = "" // likely a Go slice or array135		}136		s = "json: cannot unmarshal " + e.Value + " into " + intoWhat + e.Struct + "." + e.Field + " of type " + e.Type.String()137	} else {138		s = "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()139	}140	if e.Err != nil {141		s += ": " + e.Err.Error()142	}143	return s144}145 146func (e *UnmarshalTypeError) Unwrap() error {147	return e.Err148}149 150// An UnmarshalFieldError describes a JSON object key that151// led to an unexported (and therefore unwritable) struct field.152//153// Deprecated: No longer used; kept for compatibility.154type UnmarshalFieldError struct {155	Key   string156	Type  reflect.Type157	Field reflect.StructField158}159 160func (e *UnmarshalFieldError) Error() string {161	return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()162}163 164// An InvalidUnmarshalError describes an invalid argument passed to [Unmarshal].165// (The argument to [Unmarshal] must be a non-nil pointer.)166type InvalidUnmarshalError struct {167	Type reflect.Type168}169 170func (e *InvalidUnmarshalError) Error() string {171	if e.Type == nil {172		return "json: Unmarshal(nil)"173	}174 175	if e.Type.Kind() != reflect.Pointer {176		return "json: Unmarshal(non-pointer " + e.Type.String() + ")"177	}178	return "json: Unmarshal(nil " + e.Type.String() + ")"179}180 181// A Number represents a JSON number literal.182type Number string183 184// String returns the literal text of the number.185func (n Number) String() string { return string(n) }186 187// Float64 returns the number as a float64.188func (n Number) Float64() (float64, error) {189	return strconv.ParseFloat(string(n), 64)190}191 192// Int64 returns the number as an int64.193func (n Number) Int64() (int64, error) {194	return strconv.ParseInt(string(n), 10, 64)195}196 197var numberType = reflect.TypeFor[Number]()198 199// MarshalJSONTo implements [jsonv2.MarshalerTo].200func (n Number) MarshalJSONTo(enc *jsontext.Encoder) error {201	opts := enc.Options()202	stringify, _ := jsonv2.GetOption(opts, jsonv2.StringifyNumbers)203	if k, n := enc.StackIndex(enc.StackDepth()); k == '{' && n%2 == 0 {204		stringify = true // expecting a JSON object name205	}206	n = cmp.Or(n, "0")207	var num []byte208	val := enc.AvailableBuffer()209	if stringify {210		val = append(val, '"')211		val = append(val, n...)212		val = append(val, '"')213		num = val[len(`"`) : len(val)-len(`"`)]214	} else {215		val = append(val, n...)216		num = val217	}218	if n, err := jsonwire.ConsumeNumber(num); n != len(num) || err != nil {219		return fmt.Errorf("cannot parse %q as JSON number: %w", val, strconv.ErrSyntax)220	}221	return enc.WriteValue(val)222}223 224// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].225func (n *Number) UnmarshalJSONFrom(dec *jsontext.Decoder) error {226	opts := dec.Options()227	stringify, _ := jsonv2.GetOption(opts, jsonv2.StringifyNumbers)228	if k, n := dec.StackIndex(dec.StackDepth()); k == '{' && n%2 == 0 {229		stringify = true // expecting a JSON object name230	}231	val, err := dec.ReadValue()232	if err != nil {233		return err234	}235	val0 := val236	k := val.Kind()237	switch k {238	case 'n':239		if legacy, _ := jsonv2.GetOption(opts, MergeWithLegacySemantics); !legacy {240			*n = ""241		}242		return nil243	case '"':244		verbatim := jsonwire.ConsumeSimpleString(val) == len(val)245		val = jsonwire.UnquoteMayCopy(val, verbatim)246		if n, err := jsonwire.ConsumeNumber(val); n != len(val) || err != nil {247			return &jsonv2.SemanticError{JSONKind: val0.Kind(), JSONValue: val0.Clone(), GoType: numberType, Err: strconv.ErrSyntax}248		}249		*n = Number(val)250		return nil251	case '0':252		if stringify {253			break254		}255		*n = Number(val)256		return nil257	}258	return &jsonv2.SemanticError{JSONKind: k, GoType: numberType}259}260 
codekingpro/portable-devtools · Team Ai