| | |
| | |
| | |
| |
|
| | |
| | |
| |
|
| | |
| |
|
| | package json |
| |
|
| | import ( |
| | "encoding" |
| | "encoding/base64" |
| | "fmt" |
| | "reflect" |
| | "strconv" |
| | "strings" |
| | "unicode" |
| | "unicode/utf16" |
| | "unicode/utf8" |
| | _ "unsafe" |
| | ) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func Unmarshal(data []byte, v any) error { |
| | |
| | |
| | |
| | var d decodeState |
| | err := checkValid(data, &d.scan) |
| | if err != nil { |
| | return err |
| | } |
| |
|
| | d.init(data) |
| | return d.unmarshal(v) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | type Unmarshaler interface { |
| | UnmarshalJSON([]byte) error |
| | } |
| |
|
| | |
| | |
| | type UnmarshalTypeError struct { |
| | Value string |
| | Type reflect.Type |
| | Offset int64 |
| | Struct string |
| | Field string |
| | } |
| |
|
| | func (e *UnmarshalTypeError) Error() string { |
| | if e.Struct != "" || e.Field != "" { |
| | return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String() |
| | } |
| | return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | type UnmarshalFieldError struct { |
| | Key string |
| | Type reflect.Type |
| | Field reflect.StructField |
| | } |
| |
|
| | func (e *UnmarshalFieldError) Error() string { |
| | return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() |
| | } |
| |
|
| | |
| | |
| | type InvalidUnmarshalError struct { |
| | Type reflect.Type |
| | } |
| |
|
| | func (e *InvalidUnmarshalError) Error() string { |
| | if e.Type == nil { |
| | return "json: Unmarshal(nil)" |
| | } |
| |
|
| | if e.Type.Kind() != reflect.Pointer { |
| | return "json: Unmarshal(non-pointer " + e.Type.String() + ")" |
| | } |
| | return "json: Unmarshal(nil " + e.Type.String() + ")" |
| | } |
| |
|
| | func (d *decodeState) unmarshal(v any) error { |
| | rv := reflect.ValueOf(v) |
| | if rv.Kind() != reflect.Pointer || rv.IsNil() { |
| | return &InvalidUnmarshalError{reflect.TypeOf(v)} |
| | } |
| |
|
| | d.scan.reset() |
| | d.scanWhile(scanSkipSpace) |
| | |
| | |
| | err := d.value(rv) |
| | if err != nil { |
| | return d.addErrorContext(err) |
| | } |
| | return d.savedError |
| | } |
| |
|
| | |
| | type Number string |
| |
|
| | |
| | func (n Number) String() string { return string(n) } |
| |
|
| | |
| | func (n Number) Float64() (float64, error) { |
| | return strconv.ParseFloat(string(n), 64) |
| | } |
| |
|
| | |
| | func (n Number) Int64() (int64, error) { |
| | return strconv.ParseInt(string(n), 10, 64) |
| | } |
| |
|
| | |
| | type errorContext struct { |
| | Struct reflect.Type |
| | FieldStack []string |
| | } |
| |
|
| | |
| | type decodeState struct { |
| | data []byte |
| | off int |
| | opcode int |
| | scan scanner |
| | errorContext *errorContext |
| | savedError error |
| | useNumber bool |
| | disallowUnknownFields bool |
| | } |
| |
|
| | |
| | func (d *decodeState) readIndex() int { |
| | return d.off - 1 |
| | } |
| |
|
| | |
| | |
| | |
| | const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?" |
| |
|
| | func (d *decodeState) init(data []byte) *decodeState { |
| | d.data = data |
| | d.off = 0 |
| | d.savedError = nil |
| | if d.errorContext != nil { |
| | d.errorContext.Struct = nil |
| | |
| | d.errorContext.FieldStack = d.errorContext.FieldStack[:0] |
| | } |
| | return d |
| | } |
| |
|
| | |
| | |
| | func (d *decodeState) saveError(err error) { |
| | if d.savedError == nil { |
| | d.savedError = d.addErrorContext(err) |
| | } |
| | } |
| |
|
| | |
| | func (d *decodeState) addErrorContext(err error) error { |
| | if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) { |
| | switch err := err.(type) { |
| | case *UnmarshalTypeError: |
| | err.Struct = d.errorContext.Struct.Name() |
| | fieldStack := d.errorContext.FieldStack |
| | if err.Field != "" { |
| | fieldStack = append(fieldStack, err.Field) |
| | } |
| | err.Field = strings.Join(fieldStack, ".") |
| | } |
| | } |
| | return err |
| | } |
| |
|
| | |
| | func (d *decodeState) skip() { |
| | s, data, i := &d.scan, d.data, d.off |
| | depth := len(s.parseState) |
| | for { |
| | op := s.step(s, data[i]) |
| | i++ |
| | if len(s.parseState) < depth { |
| | d.off = i |
| | d.opcode = op |
| | return |
| | } |
| | } |
| | } |
| |
|
| | |
| | func (d *decodeState) scanNext() { |
| | if d.off < len(d.data) { |
| | d.opcode = d.scan.step(&d.scan, d.data[d.off]) |
| | d.off++ |
| | } else { |
| | d.opcode = d.scan.eof() |
| | d.off = len(d.data) + 1 |
| | } |
| | } |
| |
|
| | |
| | |
| | func (d *decodeState) scanWhile(op int) { |
| | s, data, i := &d.scan, d.data, d.off |
| | for i < len(data) { |
| | newOp := s.step(s, data[i]) |
| | i++ |
| | if newOp != op { |
| | d.opcode = newOp |
| | d.off = i |
| | return |
| | } |
| | } |
| |
|
| | d.off = len(data) + 1 |
| | d.opcode = d.scan.eof() |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func (d *decodeState) rescanLiteral() { |
| | data, i := d.data, d.off |
| | Switch: |
| | switch data[i-1] { |
| | case '"': |
| | for ; i < len(data); i++ { |
| | switch data[i] { |
| | case '\\': |
| | i++ |
| | case '"': |
| | i++ |
| | break Switch |
| | } |
| | } |
| | case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': |
| | for ; i < len(data); i++ { |
| | switch data[i] { |
| | case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
| | '.', 'e', 'E', '+', '-': |
| | default: |
| | break Switch |
| | } |
| | } |
| | case 't': |
| | i += len("rue") |
| | case 'f': |
| | i += len("alse") |
| | case 'n': |
| | i += len("ull") |
| | } |
| | if i < len(data) { |
| | d.opcode = stateEndValue(&d.scan, data[i]) |
| | } else { |
| | d.opcode = scanEnd |
| | } |
| | d.off = i + 1 |
| | } |
| |
|
| | |
| | |
| | |
| | func (d *decodeState) value(v reflect.Value) error { |
| | switch d.opcode { |
| | default: |
| | panic(phasePanicMsg) |
| |
|
| | case scanBeginArray: |
| | if v.IsValid() { |
| | if err := d.array(v); err != nil { |
| | return err |
| | } |
| | } else { |
| | d.skip() |
| | } |
| | d.scanNext() |
| |
|
| | case scanBeginObject: |
| | if v.IsValid() { |
| | if err := d.object(v); err != nil { |
| | return err |
| | } |
| | } else { |
| | d.skip() |
| | } |
| | d.scanNext() |
| |
|
| | case scanBeginLiteral: |
| | |
| | start := d.readIndex() |
| | d.rescanLiteral() |
| |
|
| | if v.IsValid() { |
| | if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil { |
| | return err |
| | } |
| | } |
| | } |
| | return nil |
| | } |
| |
|
| | type unquotedValue struct{} |
| |
|
| | |
| | |
| | |
| | |
| | func (d *decodeState) valueQuoted() any { |
| | switch d.opcode { |
| | default: |
| | panic(phasePanicMsg) |
| |
|
| | case scanBeginArray, scanBeginObject: |
| | d.skip() |
| | d.scanNext() |
| |
|
| | case scanBeginLiteral: |
| | v := d.literalInterface() |
| | switch v.(type) { |
| | case nil, string: |
| | return v |
| | } |
| | } |
| | return unquotedValue{} |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | v0 := v |
| | haveAddr := false |
| |
|
| | |
| | |
| | |
| | if v.Kind() != reflect.Pointer && v.Type().Name() != "" && v.CanAddr() { |
| | haveAddr = true |
| | v = v.Addr() |
| | } |
| | for { |
| | |
| | |
| | if v.Kind() == reflect.Interface && !v.IsNil() { |
| | e := v.Elem() |
| | if e.Kind() == reflect.Pointer && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Pointer) { |
| | haveAddr = false |
| | v = e |
| | continue |
| | } |
| | } |
| |
|
| | if v.Kind() != reflect.Pointer { |
| | break |
| | } |
| |
|
| | if decodingNull && v.CanSet() { |
| | break |
| | } |
| |
|
| | |
| | |
| | |
| | if v.Elem().Kind() == reflect.Interface && v.Elem().Elem().Equal(v) { |
| | v = v.Elem() |
| | break |
| | } |
| | if v.IsNil() { |
| | v.Set(reflect.New(v.Type().Elem())) |
| | } |
| | if v.Type().NumMethod() > 0 && v.CanInterface() { |
| | if u, ok := reflect.TypeAssert[Unmarshaler](v); ok { |
| | return u, nil, reflect.Value{} |
| | } |
| | if !decodingNull { |
| | if u, ok := reflect.TypeAssert[encoding.TextUnmarshaler](v); ok { |
| | return nil, u, reflect.Value{} |
| | } |
| | } |
| | } |
| |
|
| | if haveAddr { |
| | v = v0 |
| | haveAddr = false |
| | } else { |
| | v = v.Elem() |
| | } |
| | } |
| | return nil, nil, v |
| | } |
| |
|
| | |
| | |
| | func (d *decodeState) array(v reflect.Value) error { |
| | |
| | u, ut, pv := indirect(v, false) |
| | if u != nil { |
| | start := d.readIndex() |
| | d.skip() |
| | return u.UnmarshalJSON(d.data[start:d.off]) |
| | } |
| | if ut != nil { |
| | d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) |
| | d.skip() |
| | return nil |
| | } |
| | v = pv |
| |
|
| | |
| | switch v.Kind() { |
| | case reflect.Interface: |
| | if v.NumMethod() == 0 { |
| | |
| | ai := d.arrayInterface() |
| | v.Set(reflect.ValueOf(ai)) |
| | return nil |
| | } |
| | |
| | fallthrough |
| | default: |
| | d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) |
| | d.skip() |
| | return nil |
| | case reflect.Array, reflect.Slice: |
| | break |
| | } |
| |
|
| | i := 0 |
| | for { |
| | |
| | d.scanWhile(scanSkipSpace) |
| | if d.opcode == scanEndArray { |
| | break |
| | } |
| |
|
| | |
| | if v.Kind() == reflect.Slice { |
| | if i >= v.Cap() { |
| | v.Grow(1) |
| | } |
| | if i >= v.Len() { |
| | v.SetLen(i + 1) |
| | } |
| | } |
| |
|
| | if i < v.Len() { |
| | |
| | if err := d.value(v.Index(i)); err != nil { |
| | return err |
| | } |
| | } else { |
| | |
| | if err := d.value(reflect.Value{}); err != nil { |
| | return err |
| | } |
| | } |
| | i++ |
| |
|
| | |
| | if d.opcode == scanSkipSpace { |
| | d.scanWhile(scanSkipSpace) |
| | } |
| | if d.opcode == scanEndArray { |
| | break |
| | } |
| | if d.opcode != scanArrayValue { |
| | panic(phasePanicMsg) |
| | } |
| | } |
| |
|
| | if i < v.Len() { |
| | if v.Kind() == reflect.Array { |
| | for ; i < v.Len(); i++ { |
| | v.Index(i).SetZero() |
| | } |
| | } else { |
| | v.SetLen(i) |
| | } |
| | } |
| | if i == 0 && v.Kind() == reflect.Slice { |
| | v.Set(reflect.MakeSlice(v.Type(), 0, 0)) |
| | } |
| | return nil |
| | } |
| |
|
| | var nullLiteral = []byte("null") |
| | var textUnmarshalerType = reflect.TypeFor[encoding.TextUnmarshaler]() |
| |
|
| | |
| | |
| | func (d *decodeState) object(v reflect.Value) error { |
| | |
| | u, ut, pv := indirect(v, false) |
| | if u != nil { |
| | start := d.readIndex() |
| | d.skip() |
| | return u.UnmarshalJSON(d.data[start:d.off]) |
| | } |
| | if ut != nil { |
| | d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) |
| | d.skip() |
| | return nil |
| | } |
| | v = pv |
| | t := v.Type() |
| |
|
| | |
| | if v.Kind() == reflect.Interface && v.NumMethod() == 0 { |
| | oi := d.objectInterface() |
| | v.Set(reflect.ValueOf(oi)) |
| | return nil |
| | } |
| |
|
| | var fields structFields |
| |
|
| | |
| | |
| | |
| | |
| | switch v.Kind() { |
| | case reflect.Map: |
| | |
| | |
| | switch t.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.PointerTo(t.Key()).Implements(textUnmarshalerType) { |
| | d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) |
| | d.skip() |
| | return nil |
| | } |
| | } |
| | if v.IsNil() { |
| | v.Set(reflect.MakeMap(t)) |
| | } |
| | case reflect.Struct: |
| | fields = cachedTypeFields(t) |
| | |
| | default: |
| | d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) |
| | d.skip() |
| | return nil |
| | } |
| |
|
| | var mapElem reflect.Value |
| | var origErrorContext errorContext |
| | if d.errorContext != nil { |
| | origErrorContext = *d.errorContext |
| | } |
| |
|
| | for { |
| | |
| | d.scanWhile(scanSkipSpace) |
| | if d.opcode == scanEndObject { |
| | |
| | break |
| | } |
| | if d.opcode != scanBeginLiteral { |
| | panic(phasePanicMsg) |
| | } |
| |
|
| | |
| | start := d.readIndex() |
| | d.rescanLiteral() |
| | item := d.data[start:d.readIndex()] |
| | key, ok := unquoteBytes(item) |
| | if !ok { |
| | panic(phasePanicMsg) |
| | } |
| |
|
| | |
| | var subv reflect.Value |
| | destring := false |
| |
|
| | if v.Kind() == reflect.Map { |
| | elemType := t.Elem() |
| | if !mapElem.IsValid() { |
| | mapElem = reflect.New(elemType).Elem() |
| | } else { |
| | mapElem.SetZero() |
| | } |
| | subv = mapElem |
| | } else { |
| | f := fields.byExactName[string(key)] |
| | if f == nil { |
| | f = fields.byFoldedName[string(foldName(key))] |
| | } |
| | if f != nil { |
| | subv = v |
| | destring = f.quoted |
| | if d.errorContext == nil { |
| | d.errorContext = new(errorContext) |
| | } |
| | for i, ind := range f.index { |
| | if subv.Kind() == reflect.Pointer { |
| | if subv.IsNil() { |
| | |
| | |
| | |
| | |
| | |
| | if !subv.CanSet() { |
| | d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem())) |
| | |
| | |
| | subv = reflect.Value{} |
| | destring = false |
| | break |
| | } |
| | subv.Set(reflect.New(subv.Type().Elem())) |
| | } |
| | subv = subv.Elem() |
| | } |
| | if i < len(f.index)-1 { |
| | d.errorContext.FieldStack = append( |
| | d.errorContext.FieldStack, |
| | subv.Type().Field(ind).Name, |
| | ) |
| | } |
| | subv = subv.Field(ind) |
| | } |
| | d.errorContext.Struct = t |
| | d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name) |
| | } else if d.disallowUnknownFields { |
| | d.saveError(fmt.Errorf("json: unknown field %q", key)) |
| | } |
| | } |
| |
|
| | |
| | if d.opcode == scanSkipSpace { |
| | d.scanWhile(scanSkipSpace) |
| | } |
| | if d.opcode != scanObjectKey { |
| | panic(phasePanicMsg) |
| | } |
| | d.scanWhile(scanSkipSpace) |
| |
|
| | if destring { |
| | switch qv := d.valueQuoted().(type) { |
| | case nil: |
| | if err := d.literalStore(nullLiteral, subv, false); err != nil { |
| | return err |
| | } |
| | case string: |
| | if err := d.literalStore([]byte(qv), subv, true); err != nil { |
| | return err |
| | } |
| | default: |
| | d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) |
| | } |
| | } else { |
| | if err := d.value(subv); err != nil { |
| | return err |
| | } |
| | } |
| |
|
| | |
| | |
| | if v.Kind() == reflect.Map { |
| | kt := t.Key() |
| | var kv reflect.Value |
| | if reflect.PointerTo(kt).Implements(textUnmarshalerType) { |
| | kv = reflect.New(kt) |
| | if err := d.literalStore(item, kv, true); err != nil { |
| | return err |
| | } |
| | kv = kv.Elem() |
| | } else { |
| | switch kt.Kind() { |
| | case reflect.String: |
| | kv = reflect.New(kt).Elem() |
| | kv.SetString(string(key)) |
| | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
| | s := string(key) |
| | n, err := strconv.ParseInt(s, 10, 64) |
| | if err != nil || kt.OverflowInt(n) { |
| | d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) |
| | break |
| | } |
| | kv = reflect.New(kt).Elem() |
| | kv.SetInt(n) |
| | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: |
| | s := string(key) |
| | n, err := strconv.ParseUint(s, 10, 64) |
| | if err != nil || kt.OverflowUint(n) { |
| | d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) |
| | break |
| | } |
| | kv = reflect.New(kt).Elem() |
| | kv.SetUint(n) |
| | default: |
| | panic("json: Unexpected key type") |
| | } |
| | } |
| | if kv.IsValid() { |
| | v.SetMapIndex(kv, subv) |
| | } |
| | } |
| |
|
| | |
| | if d.opcode == scanSkipSpace { |
| | d.scanWhile(scanSkipSpace) |
| | } |
| | if d.errorContext != nil { |
| | |
| | |
| | |
| | d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)] |
| | d.errorContext.Struct = origErrorContext.Struct |
| | } |
| | if d.opcode == scanEndObject { |
| | break |
| | } |
| | if d.opcode != scanObjectValue { |
| | panic(phasePanicMsg) |
| | } |
| | } |
| | return nil |
| | } |
| |
|
| | |
| | |
| | func (d *decodeState) convertNumber(s string) (any, error) { |
| | if d.useNumber { |
| | return Number(s), nil |
| | } |
| | f, err := strconv.ParseFloat(s, 64) |
| | if err != nil { |
| | return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeFor[float64](), Offset: int64(d.off)} |
| | } |
| | return f, nil |
| | } |
| |
|
| | var numberType = reflect.TypeFor[Number]() |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error { |
| | |
| | if len(item) == 0 { |
| | |
| | d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) |
| | return nil |
| | } |
| | isNull := item[0] == 'n' |
| | u, ut, pv := indirect(v, isNull) |
| | if u != nil { |
| | return u.UnmarshalJSON(item) |
| | } |
| | if ut != nil { |
| | if item[0] != '"' { |
| | if fromQuoted { |
| | d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) |
| | return nil |
| | } |
| | val := "number" |
| | switch item[0] { |
| | case 'n': |
| | val = "null" |
| | case 't', 'f': |
| | val = "bool" |
| | } |
| | d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())}) |
| | return nil |
| | } |
| | s, ok := unquoteBytes(item) |
| | if !ok { |
| | if fromQuoted { |
| | return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) |
| | } |
| | panic(phasePanicMsg) |
| | } |
| | return ut.UnmarshalText(s) |
| | } |
| |
|
| | v = pv |
| |
|
| | switch c := item[0]; c { |
| | case 'n': |
| | |
| | |
| | if fromQuoted && string(item) != "null" { |
| | d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) |
| | break |
| | } |
| | switch v.Kind() { |
| | case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice: |
| | v.SetZero() |
| | |
| | } |
| | case 't', 'f': |
| | value := item[0] == 't' |
| | |
| | |
| | if fromQuoted && string(item) != "true" && string(item) != "false" { |
| | d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) |
| | break |
| | } |
| | switch v.Kind() { |
| | default: |
| | if fromQuoted { |
| | d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) |
| | } else { |
| | d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) |
| | } |
| | case reflect.Bool: |
| | v.SetBool(value) |
| | case reflect.Interface: |
| | if v.NumMethod() == 0 { |
| | v.Set(reflect.ValueOf(value)) |
| | } else { |
| | d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) |
| | } |
| | } |
| |
|
| | case '"': |
| | s, ok := unquoteBytes(item) |
| | if !ok { |
| | if fromQuoted { |
| | return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) |
| | } |
| | panic(phasePanicMsg) |
| | } |
| | switch v.Kind() { |
| | default: |
| | d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) |
| | case reflect.Slice: |
| | if v.Type().Elem().Kind() != reflect.Uint8 { |
| | d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) |
| | break |
| | } |
| | b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) |
| | n, err := base64.StdEncoding.Decode(b, s) |
| | if err != nil { |
| | d.saveError(err) |
| | break |
| | } |
| | v.SetBytes(b[:n]) |
| | case reflect.String: |
| | t := string(s) |
| | if v.Type() == numberType && !isValidNumber(t) { |
| | return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item) |
| | } |
| | v.SetString(t) |
| | case reflect.Interface: |
| | if v.NumMethod() == 0 { |
| | v.Set(reflect.ValueOf(string(s))) |
| | } else { |
| | d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) |
| | } |
| | } |
| |
|
| | default: |
| | if c != '-' && (c < '0' || c > '9') { |
| | if fromQuoted { |
| | return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) |
| | } |
| | panic(phasePanicMsg) |
| | } |
| | switch v.Kind() { |
| | default: |
| | if v.Kind() == reflect.String && v.Type() == numberType { |
| | |
| | |
| | v.SetString(string(item)) |
| | break |
| | } |
| | if fromQuoted { |
| | return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) |
| | } |
| | d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) |
| | case reflect.Interface: |
| | n, err := d.convertNumber(string(item)) |
| | if err != nil { |
| | d.saveError(err) |
| | break |
| | } |
| | if v.NumMethod() != 0 { |
| | d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) |
| | break |
| | } |
| | v.Set(reflect.ValueOf(n)) |
| |
|
| | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
| | n, err := strconv.ParseInt(string(item), 10, 64) |
| | if err != nil || v.OverflowInt(n) { |
| | d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())}) |
| | break |
| | } |
| | v.SetInt(n) |
| |
|
| | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: |
| | n, err := strconv.ParseUint(string(item), 10, 64) |
| | if err != nil || v.OverflowUint(n) { |
| | d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())}) |
| | break |
| | } |
| | v.SetUint(n) |
| |
|
| | case reflect.Float32, reflect.Float64: |
| | n, err := strconv.ParseFloat(string(item), v.Type().Bits()) |
| | if err != nil || v.OverflowFloat(n) { |
| | d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())}) |
| | break |
| | } |
| | v.SetFloat(n) |
| | } |
| | } |
| | return nil |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | func (d *decodeState) valueInterface() (val any) { |
| | switch d.opcode { |
| | default: |
| | panic(phasePanicMsg) |
| | case scanBeginArray: |
| | val = d.arrayInterface() |
| | d.scanNext() |
| | case scanBeginObject: |
| | val = d.objectInterface() |
| | d.scanNext() |
| | case scanBeginLiteral: |
| | val = d.literalInterface() |
| | } |
| | return |
| | } |
| |
|
| | |
| | func (d *decodeState) arrayInterface() []any { |
| | var v = make([]any, 0) |
| | for { |
| | |
| | d.scanWhile(scanSkipSpace) |
| | if d.opcode == scanEndArray { |
| | break |
| | } |
| |
|
| | v = append(v, d.valueInterface()) |
| |
|
| | |
| | if d.opcode == scanSkipSpace { |
| | d.scanWhile(scanSkipSpace) |
| | } |
| | if d.opcode == scanEndArray { |
| | break |
| | } |
| | if d.opcode != scanArrayValue { |
| | panic(phasePanicMsg) |
| | } |
| | } |
| | return v |
| | } |
| |
|
| | |
| | func (d *decodeState) objectInterface() map[string]any { |
| | m := make(map[string]any) |
| | for { |
| | |
| | d.scanWhile(scanSkipSpace) |
| | if d.opcode == scanEndObject { |
| | |
| | break |
| | } |
| | if d.opcode != scanBeginLiteral { |
| | panic(phasePanicMsg) |
| | } |
| |
|
| | |
| | start := d.readIndex() |
| | d.rescanLiteral() |
| | item := d.data[start:d.readIndex()] |
| | key, ok := unquote(item) |
| | if !ok { |
| | panic(phasePanicMsg) |
| | } |
| |
|
| | |
| | if d.opcode == scanSkipSpace { |
| | d.scanWhile(scanSkipSpace) |
| | } |
| | if d.opcode != scanObjectKey { |
| | panic(phasePanicMsg) |
| | } |
| | d.scanWhile(scanSkipSpace) |
| |
|
| | |
| | m[key] = d.valueInterface() |
| |
|
| | |
| | if d.opcode == scanSkipSpace { |
| | d.scanWhile(scanSkipSpace) |
| | } |
| | if d.opcode == scanEndObject { |
| | break |
| | } |
| | if d.opcode != scanObjectValue { |
| | panic(phasePanicMsg) |
| | } |
| | } |
| | return m |
| | } |
| |
|
| | |
| | |
| | |
| | func (d *decodeState) literalInterface() any { |
| | |
| | start := d.readIndex() |
| | d.rescanLiteral() |
| |
|
| | item := d.data[start:d.readIndex()] |
| |
|
| | switch c := item[0]; c { |
| | case 'n': |
| | return nil |
| |
|
| | case 't', 'f': |
| | return c == 't' |
| |
|
| | case '"': |
| | s, ok := unquote(item) |
| | if !ok { |
| | panic(phasePanicMsg) |
| | } |
| | return s |
| |
|
| | default: |
| | if c != '-' && (c < '0' || c > '9') { |
| | panic(phasePanicMsg) |
| | } |
| | n, err := d.convertNumber(string(item)) |
| | if err != nil { |
| | d.saveError(err) |
| | } |
| | return n |
| | } |
| | } |
| |
|
| | |
| | |
| | func getu4(s []byte) rune { |
| | if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { |
| | return -1 |
| | } |
| | var r rune |
| | for _, c := range s[2:6] { |
| | switch { |
| | case '0' <= c && c <= '9': |
| | c = c - '0' |
| | case 'a' <= c && c <= 'f': |
| | c = c - 'a' + 10 |
| | case 'A' <= c && c <= 'F': |
| | c = c - 'A' + 10 |
| | default: |
| | return -1 |
| | } |
| | r = r*16 + rune(c) |
| | } |
| | return r |
| | } |
| |
|
| | |
| | |
| | func unquote(s []byte) (t string, ok bool) { |
| | s, ok = unquoteBytes(s) |
| | t = string(s) |
| | return |
| | } |
| |
|
| | func unquoteBytes(s []byte) (t []byte, ok bool) { |
| | if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { |
| | return |
| | } |
| | s = s[1 : len(s)-1] |
| |
|
| | |
| | |
| | |
| | r := 0 |
| | for r < len(s) { |
| | c := s[r] |
| | if c == '\\' || c == '"' || c < ' ' { |
| | break |
| | } |
| | rr, size := utf8.DecodeRune(s[r:]) |
| | if rr == utf8.RuneError && size == 1 { |
| | break |
| | } |
| | r += size |
| | } |
| | if r == len(s) { |
| | return s, true |
| | } |
| |
|
| | b := make([]byte, len(s)+2*utf8.UTFMax) |
| | w := copy(b, s[0:r]) |
| | for r < len(s) { |
| | |
| | |
| | |
| | if w >= len(b)-2*utf8.UTFMax { |
| | nb := make([]byte, (len(b)+utf8.UTFMax)*2) |
| | copy(nb, b[0:w]) |
| | b = nb |
| | } |
| | switch c := s[r]; { |
| | case c == '\\': |
| | r++ |
| | if r >= len(s) { |
| | return |
| | } |
| | switch s[r] { |
| | default: |
| | return |
| | case '"', '\\', '/', '\'': |
| | b[w] = s[r] |
| | r++ |
| | w++ |
| | case 'b': |
| | b[w] = '\b' |
| | r++ |
| | w++ |
| | case 'f': |
| | b[w] = '\f' |
| | r++ |
| | w++ |
| | case 'n': |
| | b[w] = '\n' |
| | r++ |
| | w++ |
| | case 'r': |
| | b[w] = '\r' |
| | r++ |
| | w++ |
| | case 't': |
| | b[w] = '\t' |
| | r++ |
| | w++ |
| | case 'u': |
| | r-- |
| | rr := getu4(s[r:]) |
| | if rr < 0 { |
| | return |
| | } |
| | r += 6 |
| | if utf16.IsSurrogate(rr) { |
| | rr1 := getu4(s[r:]) |
| | if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { |
| | |
| | r += 6 |
| | w += utf8.EncodeRune(b[w:], dec) |
| | break |
| | } |
| | |
| | rr = unicode.ReplacementChar |
| | } |
| | w += utf8.EncodeRune(b[w:], rr) |
| | } |
| |
|
| | |
| | case c == '"', c < ' ': |
| | return |
| |
|
| | |
| | case c < utf8.RuneSelf: |
| | b[w] = c |
| | r++ |
| | w++ |
| |
|
| | |
| | default: |
| | rr, size := utf8.DecodeRune(s[r:]) |
| | r += size |
| | w += utf8.EncodeRune(b[w:], rr) |
| | } |
| | } |
| | return b[0:w], true |
| | } |
| |
|