Source File
decode.go
Belonging Package
encoding/json
package json
import (
)
var decodeState
:= checkValid(, &.scan)
if != nil {
return
}
.init()
return .unmarshal()
}
type Unmarshaler interface {
UnmarshalJSON([]byte) error
}
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 struct type containing the field
Field string // the full path from root node to the field
}
func ( *UnmarshalTypeError) () string {
if .Struct != "" || .Field != "" {
return "json: cannot unmarshal " + .Value + " into Go struct field " + .Struct + "." + .Field + " of type " + .Type.String()
}
return "json: cannot unmarshal " + .Value + " into Go value of type " + .Type.String()
}
type InvalidUnmarshalError struct {
Type reflect.Type
}
func ( *InvalidUnmarshalError) () string {
if .Type == nil {
return "json: Unmarshal(nil)"
}
if .Type.Kind() != reflect.Ptr {
return "json: Unmarshal(non-pointer " + .Type.String() + ")"
}
return "json: Unmarshal(nil " + .Type.String() + ")"
}
func ( *decodeState) ( interface{}) error {
:= reflect.ValueOf()
if .Kind() != reflect.Ptr || .IsNil() {
return &InvalidUnmarshalError{reflect.TypeOf()}
}
.scan.reset()
:= .value()
if != nil {
return .addErrorContext()
}
return .savedError
}
type decodeState struct {
data []byte
off int // next read offset in data
opcode int // last read result
scan scanner
errorContext struct { // provides context for type errors
Struct reflect.Type
FieldStack []string
}
savedError error
useNumber bool
disallowUnknownFields bool
}
func ( *decodeState) () int {
return .off - 1
}
const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?"
func ( *decodeState) ( []byte) *decodeState {
.data =
.off = 0
.savedError = nil
.errorContext.Struct = nil
.errorContext.FieldStack = .errorContext.FieldStack[:0]
return
}
func ( *decodeState) ( error) {
if .savedError == nil {
.savedError = .addErrorContext()
}
}
func ( *decodeState) ( error) error {
if .errorContext.Struct != nil || len(.errorContext.FieldStack) > 0 {
switch err := .(type) {
case *UnmarshalTypeError:
.Struct = .errorContext.Struct.Name()
.Field = strings.Join(.errorContext.FieldStack, ".")
return
}
}
return
}
func ( *decodeState) () {
, , := &.scan, .data, .off
:= len(.parseState)
for {
:= .step(, [])
++
if len(.parseState) < {
.off =
.opcode =
return
}
}
}
func ( *decodeState) () {
, := .data, .off
:
switch [-1] {
case '"': // string
for ; < len(); ++ {
switch [] {
case '\\':
++ // escaped char
case '"':
++ // tokenize the closing quote too
break
}
}
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': // number
for ; < len(); ++ {
switch [] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'.', 'e', 'E', '+', '-':
default:
break
}
}
case 't': // true
+= len("rue")
case 'f': // false
+= len("alse")
case 'n': // null
+= len("ull")
}
if < len() {
.opcode = stateEndValue(&.scan, [])
} else {
.opcode = scanEnd
}
.off = + 1
}
func ( *decodeState) ( reflect.Value) error {
switch .opcode {
default:
panic(phasePanicMsg)
case scanBeginArray:
if .IsValid() {
if := .array(); != nil {
return
}
} else {
.skip()
}
.scanNext()
case scanBeginObject:
if .IsValid() {
if := .object(); != nil {
return
}
} else {
.skip()
}
.scanNext()
:= .readIndex()
.rescanLiteral()
if .IsValid() {
if := .literalStore(.data[:.readIndex()], , false); != nil {
return
}
}
}
return nil
}
type unquotedValue struct{}
func ( *decodeState) () interface{} {
switch .opcode {
default:
panic(phasePanicMsg)
case scanBeginArray, scanBeginObject:
.skip()
.scanNext()
case scanBeginLiteral:
:= .literalInterface()
switch .(type) {
case nil, string:
return
}
}
return unquotedValue{}
}
:=
:= false
if .Elem().Kind() == reflect.Interface && .Elem().Elem() == {
= .Elem()
break
}
if .IsNil() {
.Set(reflect.New(.Type().Elem()))
}
if .Type().NumMethod() > 0 && .CanInterface() {
if , := .Interface().(Unmarshaler); {
return , nil, reflect.Value{}
}
if ! {
if , := .Interface().(encoding.TextUnmarshaler); {
return nil, , reflect.Value{}
}
}
}
if {
= // restore original value after round-trip Value.Addr().Elem()
= false
} else {
= .Elem()
}
}
return nil, nil,
}
:= .arrayInterface()
.Set(reflect.ValueOf())
return nil
.scanWhile(scanSkipSpace)
if .opcode == scanEndArray {
break
}
if .opcode == scanSkipSpace {
.scanWhile(scanSkipSpace)
}
if .opcode == scanEndArray {
break
}
if .opcode != scanArrayValue {
panic(phasePanicMsg)
}
}
if < .Len() {
if .Kind() == reflect.Interface && .NumMethod() == 0 {
:= .objectInterface()
.Set(reflect.ValueOf())
return nil
}
var structFields
switch .Kind() {
switch .Key().Kind() {
case reflect.String,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
default:
if !reflect.PtrTo(.Key()).Implements(textUnmarshalerType) {
.saveError(&UnmarshalTypeError{Value: "object", Type: , Offset: int64(.off)})
.skip()
return nil
}
}
if .IsNil() {
.Set(reflect.MakeMap())
}
case reflect.Struct:
break
}
if .opcode != scanBeginLiteral {
panic(phasePanicMsg)
}
:= .readIndex()
.rescanLiteral()
:= .data[:.readIndex()]
, := unquoteBytes()
if ! {
panic(phasePanicMsg)
}
= &.list[]
if !.CanSet() {
= reflect.Value{}
= false
break
}
.Set(reflect.New(.Type().Elem()))
}
= .Elem()
}
= .Field()
}
.errorContext.FieldStack = append(.errorContext.FieldStack, .name)
.errorContext.Struct =
} else if .disallowUnknownFields {
.saveError(fmt.Errorf("json: unknown field %q", ))
}
}
if .opcode == scanSkipSpace {
.scanWhile(scanSkipSpace)
}
if .opcode != scanObjectKey {
panic(phasePanicMsg)
}
.scanWhile(scanSkipSpace)
if {
switch qv := .valueQuoted().(type) {
case nil:
if := .literalStore(nullLiteral, , false); != nil {
return
}
case string:
if := .literalStore([]byte(), , true); != nil {
return
}
default:
.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", .Type()))
}
} else {
if := .value(); != nil {
return
}
}
if .Kind() == reflect.Map {
:= .Key()
var reflect.Value
switch {
case reflect.PtrTo().Implements(textUnmarshalerType):
= reflect.New()
if := .literalStore(, , true); != nil {
return
}
= .Elem()
case .Kind() == reflect.String:
= reflect.ValueOf().Convert()
default:
switch .Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
:= string()
, := strconv.ParseInt(, 10, 64)
if != nil || reflect.Zero().OverflowInt() {
.saveError(&UnmarshalTypeError{Value: "number " + , Type: , Offset: int64( + 1)})
break
}
= reflect.ValueOf().Convert()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
:= string()
, := strconv.ParseUint(, 10, 64)
if != nil || reflect.Zero().OverflowUint() {
.saveError(&UnmarshalTypeError{Value: "number " + , Type: , Offset: int64( + 1)})
break
}
= reflect.ValueOf().Convert()
default:
panic("json: Unexpected key type") // should never occur
}
}
if .IsValid() {
.SetMapIndex(, )
}
}
if .opcode == scanSkipSpace {
.scanWhile(scanSkipSpace)
.errorContext.FieldStack = .errorContext.FieldStack[:len(.FieldStack)]
.errorContext.Struct = .Struct
if .opcode == scanEndObject {
break
}
if .opcode != scanObjectValue {
panic(phasePanicMsg)
}
}
return nil
}
.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", , .Type()))
return nil
}
:= [0] == 'n' // null
, , := indirect(, )
if != nil {
return .UnmarshalJSON()
}
if != nil {
if [0] != '"' {
if {
.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", , .Type()))
return nil
}
:= "number"
switch [0] {
case 'n':
= "null"
case 't', 'f':
= "bool"
}
.saveError(&UnmarshalTypeError{Value: , Type: .Type(), Offset: int64(.readIndex())})
return nil
}
, := unquoteBytes()
if ! {
if {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", , .Type())
}
panic(phasePanicMsg)
}
return .UnmarshalText()
}
=
switch := [0]; {
}
case 't', 'f': // true, false
if && string() != "true" && string() != "false" {
.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", , .Type()))
break
}
switch .Kind() {
default:
if {
.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", , .Type()))
} else {
.saveError(&UnmarshalTypeError{Value: "bool", Type: .Type(), Offset: int64(.readIndex())})
}
case reflect.Bool:
.SetBool()
case reflect.Interface:
if .NumMethod() == 0 {
.Set(reflect.ValueOf())
} else {
.saveError(&UnmarshalTypeError{Value: "bool", Type: .Type(), Offset: int64(.readIndex())})
}
}
case '"': // string
, := unquoteBytes()
if ! {
if {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", , .Type())
}
panic(phasePanicMsg)
}
switch .Kind() {
default:
.saveError(&UnmarshalTypeError{Value: "string", Type: .Type(), Offset: int64(.readIndex())})
case reflect.Slice:
if .Type().Elem().Kind() != reflect.Uint8 {
.saveError(&UnmarshalTypeError{Value: "string", Type: .Type(), Offset: int64(.readIndex())})
break
}
:= make([]byte, base64.StdEncoding.DecodedLen(len()))
, := base64.StdEncoding.Decode(, )
if != nil {
.saveError()
break
}
.SetBytes([:])
case reflect.String:
if .Type() == numberType && !isValidNumber(string()) {
return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", )
}
.SetString(string())
case reflect.Interface:
if .NumMethod() == 0 {
.Set(reflect.ValueOf(string()))
} else {
.saveError(&UnmarshalTypeError{Value: "string", Type: .Type(), Offset: int64(.readIndex())})
}
}
default: // number
if != '-' && ( < '0' || > '9') {
if {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", , .Type())
}
panic(phasePanicMsg)
}
:= string()
switch .Kind() {
default:
.SetString()
break
}
if {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", , .Type())
}
.saveError(&UnmarshalTypeError{Value: "number", Type: .Type(), Offset: int64(.readIndex())})
case reflect.Interface:
, := .convertNumber()
if != nil {
.saveError()
break
}
if .NumMethod() != 0 {
.saveError(&UnmarshalTypeError{Value: "number", Type: .Type(), Offset: int64(.readIndex())})
break
}
.Set(reflect.ValueOf())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
, := strconv.ParseInt(, 10, 64)
if != nil || .OverflowInt() {
.saveError(&UnmarshalTypeError{Value: "number " + , Type: .Type(), Offset: int64(.readIndex())})
break
}
.SetInt()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
, := strconv.ParseUint(, 10, 64)
if != nil || .OverflowUint() {
.saveError(&UnmarshalTypeError{Value: "number " + , Type: .Type(), Offset: int64(.readIndex())})
break
}
.SetUint()
case reflect.Float32, reflect.Float64:
, := strconv.ParseFloat(, .Type().Bits())
if != nil || .OverflowFloat() {
.saveError(&UnmarshalTypeError{Value: "number " + , Type: .Type(), Offset: int64(.readIndex())})
break
}
.SetFloat()
}
}
return nil
}
func ( *decodeState) () ( interface{}) {
switch .opcode {
default:
panic(phasePanicMsg)
case scanBeginArray:
= .arrayInterface()
.scanNext()
case scanBeginObject:
= .objectInterface()
.scanNext()
case scanBeginLiteral:
= .literalInterface()
}
return
}
func ( *decodeState) () []interface{} {
var = make([]interface{}, 0)
.scanWhile(scanSkipSpace)
if .opcode == scanEndArray {
break
}
= append(, .valueInterface())
if .opcode == scanSkipSpace {
.scanWhile(scanSkipSpace)
}
if .opcode == scanEndArray {
break
}
if .opcode != scanArrayValue {
panic(phasePanicMsg)
}
}
return
}
func ( *decodeState) () map[string]interface{} {
:= make(map[string]interface{})
break
}
if .opcode != scanBeginLiteral {
panic(phasePanicMsg)
}
:= .readIndex()
.rescanLiteral()
:= .data[:.readIndex()]
, := unquote()
if ! {
panic(phasePanicMsg)
}
if .opcode == scanSkipSpace {
.scanWhile(scanSkipSpace)
}
if .opcode != scanObjectKey {
panic(phasePanicMsg)
}
.scanWhile(scanSkipSpace)
[] = .valueInterface()
if .opcode == scanSkipSpace {
.scanWhile(scanSkipSpace)
}
if .opcode == scanEndObject {
break
}
if .opcode != scanObjectValue {
panic(phasePanicMsg)
}
}
return
}
:= .readIndex()
.rescanLiteral()
:= .data[:.readIndex()]
switch := [0]; {
case 'n': // null
return nil
case 't', 'f': // true, false
return == 't'
case '"': // string
, := unquote()
if ! {
panic(phasePanicMsg)
}
return
default: // number
if != '-' && ( < '0' || > '9') {
panic(phasePanicMsg)
}
, := .convertNumber(string())
if != nil {
.saveError()
}
return
}
}
if >= len()-2*utf8.UTFMax {
:= make([]byte, (len()+utf8.UTFMax)*2)
copy(, [0:])
=
}
switch := []; {
case == '\\':
++
if >= len() {
return
}
switch [] {
default:
return
case '"', '\\', '/', '\'':
[] = []
++
++
case 'b':
[] = '\b'
++
++
case 'f':
[] = '\f'
++
++
case 'n':
[] = '\n'
++
++
case 'r':
[] = '\r'
++
++
case 't':
[] = '\t'
++
++
case 'u':
--
:= getu4([:])
if < 0 {
return
}
+= 6
if utf16.IsSurrogate() {
:= getu4([:])
+= 6
+= utf8.EncodeRune([:], )
break
= unicode.ReplacementChar
}
+= utf8.EncodeRune([:], )
}
case == '"', < ' ':
return
default:
, := utf8.DecodeRune([:])
+=
+= utf8.EncodeRune([:], )
}
}
return [0:], true
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |