// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build goexperiment.jsonv2

// Represents JSON data structure using native Go types: booleans, floats,
// strings, arrays, and maps.

package json

import (
	
	
	
	

	
	
	jsonv2 
)

// 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
//   - []any, for JSON arrays
//   - map[string]any, 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 ( []byte,  any) error {
	return jsonv2.Unmarshal(, , DefaultOptionsV1())
}

// Unmarshaler is the interface implemented by types
// that can unmarshal a JSON description of themselves.
// The input can be assumed to be a valid encoding of
// a JSON value. UnmarshalJSON must copy the JSON data
// if it wishes to retain the data after returning.
type Unmarshaler = jsonv2.Unmarshaler

// An UnmarshalTypeError describes a JSON value that was
// not appropriate for a value of a specific Go type.
type UnmarshalTypeError struct {
	Value  string       // description of JSON value - "bool", "array", "number -5"
	Type   reflect.Type // type of Go value it could not be assigned to
	Offset int64        // error occurred after reading Offset bytes
	Struct string       // name of the root type containing the field
	Field  string       // the full path from root node to the value
	Err    error        // may be nil
}

func ( *UnmarshalTypeError) () string {
	 := "json: cannot unmarshal"
	if .Value != "" {
		 += " JSON " + .Value
	}
	 += " into"
	var  string
	if .Field != "" {
		 += " " + .Struct + "." + .Field
		 = " of"
	}
	if .Type != nil {
		 += 
		 += " Go type " + .Type.String()
	}
	if .Err != nil {
		 += ": " + .Err.Error()
	}
	return 
}

func ( *UnmarshalTypeError) () error {
	return .Err
}

// An UnmarshalFieldError describes a JSON object key that
// led to an unexported (and therefore unwritable) struct field.
//
// Deprecated: No longer used; kept for compatibility.
type UnmarshalFieldError struct {
	Key   string
	Type  reflect.Type
	Field reflect.StructField
}

func ( *UnmarshalFieldError) () string {
	return "json: cannot unmarshal object key " + strconv.Quote(.Key) + " into unexported field " + .Field.Name + " of type " + .Type.String()
}

// An InvalidUnmarshalError describes an invalid argument passed to [Unmarshal].
// (The argument to [Unmarshal] must be a non-nil pointer.)
type InvalidUnmarshalError struct {
	Type reflect.Type
}

func ( *InvalidUnmarshalError) () string {
	if .Type == nil {
		return "json: Unmarshal(nil)"
	}

	if .Type.Kind() != reflect.Pointer {
		return "json: Unmarshal(non-pointer " + .Type.String() + ")"
	}
	return "json: Unmarshal(nil " + .Type.String() + ")"
}

// A Number represents a JSON number literal.
type Number string

// String returns the literal text of the number.
func ( Number) () string { return string() }

// Float64 returns the number as a float64.
func ( Number) () (float64, error) {
	return strconv.ParseFloat(string(), 64)
}

// Int64 returns the number as an int64.
func ( Number) () (int64, error) {
	return strconv.ParseInt(string(), 10, 64)
}

var numberType = reflect.TypeFor[Number]()

// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( Number) ( *jsontext.Encoder) error {
	 := .Options()
	,  := jsonv2.GetOption(, jsonv2.StringifyNumbers)
	if ,  := .StackIndex(.StackDepth());  == '{' && %2 == 0 {
		 = true // expecting a JSON object name
	}
	 = cmp.Or(, "0")
	var  []byte
	 := .UnusedBuffer()
	if  {
		 = append(, '"')
		 = append(, ...)
		 = append(, '"')
		 = [len(`"`) : len()-len(`"`)]
	} else {
		 = append(, ...)
		 = 
	}
	if ,  := jsonwire.ConsumeNumber();  != len() ||  != nil {
		return fmt.Errorf("cannot parse %q as JSON number: %w", , strconv.ErrSyntax)
	}
	return .WriteValue()
}

// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( *Number) ( *jsontext.Decoder) error {
	 := .Options()
	,  := jsonv2.GetOption(, jsonv2.StringifyNumbers)
	if ,  := .StackIndex(.StackDepth());  == '{' && %2 == 0 {
		 = true // expecting a JSON object name
	}
	,  := .ReadValue()
	if  != nil {
		return 
	}
	 := 
	 := .Kind()
	switch  {
	case 'n':
		if ,  := jsonv2.GetOption(, MergeWithLegacySemantics); ! {
			* = ""
		}
		return nil
	case '"':
		 := jsonwire.ConsumeSimpleString() == len()
		 = jsonwire.UnquoteMayCopy(, )
		if ,  := jsonwire.ConsumeNumber();  != len() ||  != nil {
			return &jsonv2.SemanticError{JSONKind: .Kind(), JSONValue: .Clone(), GoType: numberType, Err: strconv.ErrSyntax}
		}
		* = Number()
		return nil
	case '0':
		if  {
			break
		}
		* = Number()
		return nil
	}
	return &jsonv2.SemanticError{JSONKind: , GoType: numberType}
}