mirror of
https://github.com/json-iterator/go.git
synced 2025-04-17 11:26:35 +02:00
Formated, doced. Also fixed few minor bugs.
This commit is contained in:
parent
97849e019f
commit
d63a00f0bf
@ -1,3 +1,5 @@
|
|||||||
|
[](https://goreportcard.com/report/github.com/json-iterator/go)
|
||||||
|
|
||||||
jsoniter (json-iterator) is fast and flexible JSON parser available in [Java](https://github.com/json-iterator/java) and [Go](https://github.com/json-iterator/go)
|
jsoniter (json-iterator) is fast and flexible JSON parser available in [Java](https://github.com/json-iterator/java) and [Go](https://github.com/json-iterator/go)
|
||||||
|
|
||||||
# Why jsoniter?
|
# Why jsoniter?
|
||||||
@ -37,7 +39,7 @@ import "github.com/json-iterator/go"
|
|||||||
iter := ParseString(`[0, [1, 2], [3, 4], 5]`)
|
iter := ParseString(`[0, [1, 2], [3, 4], 5]`)
|
||||||
count := 0
|
count := 0
|
||||||
for iter.ReadArray() {
|
for iter.ReadArray() {
|
||||||
iter.skip()
|
iter.Skip()
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
fmt.Println(count) // 4
|
fmt.Println(count) // 4
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_get_from_map(t *testing.T) {
|
func Test_get_from_map(t *testing.T) {
|
||||||
@ -36,7 +36,7 @@ func Test_is_null(t *testing.T) {
|
|||||||
any := Any{val: []interface{}{
|
any := Any{val: []interface{}{
|
||||||
1, 2, 3,
|
1, 2, 3,
|
||||||
}}
|
}}
|
||||||
if any.IsNull() != false {
|
if any.IsNil() != false {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,7 @@ package jsoniter
|
|||||||
|
|
||||||
import "io"
|
import "io"
|
||||||
|
|
||||||
// adapt to json/encoding api
|
// Unmarshal adapts to json/encoding APIs
|
||||||
|
|
||||||
func Unmarshal(data []byte, v interface{}) error {
|
func Unmarshal(data []byte, v interface{}) error {
|
||||||
iter := ParseBytes(data)
|
iter := ParseBytes(data)
|
||||||
iter.Read(v)
|
iter.Read(v)
|
||||||
|
198
feature_any.go
198
feature_any.go
@ -6,104 +6,109 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Any API is for maximum flexibility
|
||||||
type Any struct {
|
type Any struct {
|
||||||
val interface{}
|
val interface{}
|
||||||
Error error
|
Error error
|
||||||
LastAccessed interface{}
|
LastAccessed interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeAny creates Any instance
|
||||||
func MakeAny(val interface{}) *Any {
|
func MakeAny(val interface{}) *Any {
|
||||||
return &Any{val, nil, nil}
|
return &Any{val, nil, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get extracts a json object from Any
|
||||||
func (any *Any) Get(keys ...interface{}) interface{} {
|
func (any *Any) Get(keys ...interface{}) interface{} {
|
||||||
ret, err := getPath(any.val, keys...)
|
ret, err := getPath(any.val, keys...)
|
||||||
any.LastAccessed = ret
|
any.LastAccessed = ret
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return "";
|
return ""
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetValueType gets type of a value
|
||||||
func (any *Any) GetValueType(keys ...interface{}) ValueType {
|
func (any *Any) GetValueType(keys ...interface{}) ValueType {
|
||||||
ret, err := getPath(any.val, keys...)
|
ret, err := getPath(any.val, keys...)
|
||||||
any.LastAccessed = ret
|
any.LastAccessed = ret
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return Invalid;
|
return Invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
switch reflect.TypeOf(ret).Kind() {
|
switch reflect.TypeOf(ret).Kind() {
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Int32:
|
case reflect.Int32:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Uint:
|
case reflect.Uint:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
return Number;
|
return Number
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return String;
|
return String
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
return Bool;
|
return Bool
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
return Array;
|
return Array
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return Object;
|
return Object
|
||||||
default:
|
default:
|
||||||
return Invalid
|
return Invalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToString converts a json object to string
|
||||||
func (any *Any) ToString(keys ...interface{}) string {
|
func (any *Any) ToString(keys ...interface{}) string {
|
||||||
ret, err := getPath(any.val, keys...)
|
ret, err := getPath(any.val, keys...)
|
||||||
any.LastAccessed = ret
|
any.LastAccessed = ret
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return "";
|
return ""
|
||||||
}
|
}
|
||||||
switch ret := ret.(type) {
|
switch ret := ret.(type) {
|
||||||
case uint8:
|
case uint8:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case int8:
|
case int8:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case uint16:
|
case uint16:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case int16:
|
case int16:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case uint32:
|
case uint32:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case int32:
|
case int32:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case uint64:
|
case uint64:
|
||||||
return strconv.FormatUint(uint64(ret), 10);
|
return strconv.FormatUint(uint64(ret), 10)
|
||||||
case int64:
|
case int64:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case int:
|
case int:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case uint:
|
case uint:
|
||||||
return strconv.FormatInt(int64(ret), 10);
|
return strconv.FormatInt(int64(ret), 10)
|
||||||
case float32:
|
case float32:
|
||||||
return strconv.FormatFloat(float64(ret), 'E', -1, 32);
|
return strconv.FormatFloat(float64(ret), 'E', -1, 32)
|
||||||
case float64:
|
case float64:
|
||||||
return strconv.FormatFloat(ret, 'E', -1, 64);
|
return strconv.FormatFloat(ret, 'E', -1, 64)
|
||||||
case string:
|
case string:
|
||||||
return ret
|
return ret
|
||||||
default:
|
default:
|
||||||
@ -111,135 +116,149 @@ func (any *Any) ToString(keys ...interface{}) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUint8 converts a json object to Uint8
|
||||||
func (any *Any) ToUint8(keys ...interface{}) uint8 {
|
func (any *Any) ToUint8(keys ...interface{}) uint8 {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return uint8(ret)
|
return uint8(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToInt8 converts a json object to Int8
|
||||||
func (any *Any) ToInt8(keys ...interface{}) int8 {
|
func (any *Any) ToInt8(keys ...interface{}) int8 {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return int8(ret)
|
return int8(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUint16 converts a json object to Uint16
|
||||||
func (any *Any) ToUint16(keys ...interface{}) uint16 {
|
func (any *Any) ToUint16(keys ...interface{}) uint16 {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return uint16(ret)
|
return uint16(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToInt16 converts a json object to Int16
|
||||||
func (any *Any) ToInt16(keys ...interface{}) int16 {
|
func (any *Any) ToInt16(keys ...interface{}) int16 {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return int16(ret)
|
return int16(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUint32 converts a json object to Uint32
|
||||||
func (any *Any) ToUint32(keys ...interface{}) uint32 {
|
func (any *Any) ToUint32(keys ...interface{}) uint32 {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return uint32(ret)
|
return uint32(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToInt32 converts a json object to Int32
|
||||||
func (any *Any) ToInt32(keys ...interface{}) int32 {
|
func (any *Any) ToInt32(keys ...interface{}) int32 {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return int32(ret)
|
return int32(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUint64 converts a json object to Uint64
|
||||||
func (any *Any) ToUint64(keys ...interface{}) uint64 {
|
func (any *Any) ToUint64(keys ...interface{}) uint64 {
|
||||||
ret, err := getPathAsUint64(any, keys...)
|
ret, err := getPathAsUint64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return uint64(ret)
|
return uint64(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToInt64 converts a json object to Int64
|
||||||
func (any *Any) ToInt64(keys ...interface{}) int64 {
|
func (any *Any) ToInt64(keys ...interface{}) int64 {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return int64(ret)
|
return int64(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToInt converts a json object to Int
|
||||||
func (any *Any) ToInt(keys ...interface{}) int {
|
func (any *Any) ToInt(keys ...interface{}) int {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return int(ret)
|
return int(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUint converts a json object to Uint
|
||||||
func (any *Any) ToUint(keys ...interface{}) uint {
|
func (any *Any) ToUint(keys ...interface{}) uint {
|
||||||
ret, err := getPathAsInt64(any, keys...)
|
ret, err := getPathAsInt64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return uint(ret)
|
return uint(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToFloat32 converts a json object to Float32
|
||||||
func (any *Any) ToFloat32(keys ...interface{}) float32 {
|
func (any *Any) ToFloat32(keys ...interface{}) float32 {
|
||||||
ret, err := getPathAsFloat64(any, keys...)
|
ret, err := getPathAsFloat64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return float32(ret)
|
return float32(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToFloat64 converts a json object to Float64
|
||||||
func (any *Any) ToFloat64(keys ...interface{}) float64 {
|
func (any *Any) ToFloat64(keys ...interface{}) float64 {
|
||||||
ret, err := getPathAsFloat64(any, keys...)
|
ret, err := getPathAsFloat64(any, keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToBool converts a json object to Bool
|
||||||
func (any *Any) ToBool(keys ...interface{}) bool {
|
func (any *Any) ToBool(keys ...interface{}) bool {
|
||||||
ret, err := getPath(any.val, keys...)
|
ret, err := getPath(any.val, keys...)
|
||||||
any.LastAccessed = ret
|
any.LastAccessed = ret
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
typedRet, ok := ret.(bool)
|
typedRet, ok := ret.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
any.Error = fmt.Errorf("%v is not bool", ret)
|
any.Error = fmt.Errorf("%v is not bool", ret)
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
return typedRet
|
return typedRet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *Any) IsNull(keys ...interface{}) bool {
|
// IsNil judges whether a json object is nil
|
||||||
|
func (any *Any) IsNil(keys ...interface{}) bool {
|
||||||
ret, err := getPath(any.val, keys...)
|
ret, err := getPath(any.val, keys...)
|
||||||
any.LastAccessed = ret
|
any.LastAccessed = ret
|
||||||
if err != nil {
|
if err != nil {
|
||||||
any.Error = err
|
any.Error = err
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
return reflect.ValueOf(ret).IsNil()
|
return reflect.ValueOf(ret).IsNil()
|
||||||
}
|
}
|
||||||
@ -253,35 +272,35 @@ func getPathAsInt64(any *Any, keys ...interface{}) (int64, error) {
|
|||||||
}
|
}
|
||||||
switch ret := ret.(type) {
|
switch ret := ret.(type) {
|
||||||
case uint8:
|
case uint8:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case int8:
|
case int8:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case uint16:
|
case uint16:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case int16:
|
case int16:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case uint32:
|
case uint32:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case int32:
|
case int32:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case uint64:
|
case uint64:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case int64:
|
case int64:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case int:
|
case int:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case uint:
|
case uint:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case float32:
|
case float32:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case float64:
|
case float64:
|
||||||
return int64(ret), nil;
|
return int64(ret), nil
|
||||||
case string:
|
case string:
|
||||||
intVal, err := strconv.ParseInt(ret, 10, 64)
|
intVal, err := strconv.ParseInt(ret, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return intVal, nil;
|
return intVal, nil
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("%v is not number", ret)
|
return 0, fmt.Errorf("%v is not number", ret)
|
||||||
}
|
}
|
||||||
@ -296,35 +315,35 @@ func getPathAsUint64(any *Any, keys ...interface{}) (uint64, error) {
|
|||||||
}
|
}
|
||||||
switch ret := ret.(type) {
|
switch ret := ret.(type) {
|
||||||
case uint8:
|
case uint8:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case int8:
|
case int8:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case uint16:
|
case uint16:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case int16:
|
case int16:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case uint32:
|
case uint32:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case int32:
|
case int32:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case uint64:
|
case uint64:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case int64:
|
case int64:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case int:
|
case int:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case uint:
|
case uint:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case float32:
|
case float32:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case float64:
|
case float64:
|
||||||
return uint64(ret), nil;
|
return uint64(ret), nil
|
||||||
case string:
|
case string:
|
||||||
intVal, err := strconv.ParseUint(ret, 10, 64)
|
intVal, err := strconv.ParseUint(ret, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return intVal, nil;
|
return intVal, nil
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("%v is not number", ret)
|
return 0, fmt.Errorf("%v is not number", ret)
|
||||||
}
|
}
|
||||||
@ -339,43 +358,43 @@ func getPathAsFloat64(any *Any, keys ...interface{}) (float64, error) {
|
|||||||
}
|
}
|
||||||
switch ret := ret.(type) {
|
switch ret := ret.(type) {
|
||||||
case uint8:
|
case uint8:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case int8:
|
case int8:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case uint16:
|
case uint16:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case int16:
|
case int16:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case uint32:
|
case uint32:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case int32:
|
case int32:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case uint64:
|
case uint64:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case int64:
|
case int64:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case int:
|
case int:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case uint:
|
case uint:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case float32:
|
case float32:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case float64:
|
case float64:
|
||||||
return float64(ret), nil;
|
return float64(ret), nil
|
||||||
case string:
|
case string:
|
||||||
floatVal, err := strconv.ParseFloat(ret, 64)
|
floatVal, err := strconv.ParseFloat(ret, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return floatVal, nil;
|
return floatVal, nil
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("%v is not number", ret)
|
return 0, fmt.Errorf("%v is not number", ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPath(val interface{}, keys ...interface{}) (interface{}, error) {
|
func getPath(val interface{}, keys ...interface{}) (interface{}, error) {
|
||||||
if (len(keys) == 0) {
|
if len(keys) == 0 {
|
||||||
return val, nil;
|
return val, nil
|
||||||
}
|
}
|
||||||
switch key := keys[0].(type) {
|
switch key := keys[0].(type) {
|
||||||
case string:
|
case string:
|
||||||
@ -395,9 +414,8 @@ func getPath(val interface{}, keys ...interface{}) (interface{}, error) {
|
|||||||
copy(nextKeys, keys[1:])
|
copy(nextKeys, keys[1:])
|
||||||
return getPath(nextVal, nextKeys...)
|
return getPath(nextVal, nextKeys...)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%v is not string or int", keys[0]);
|
return nil, fmt.Errorf("%v is not string or int", keys[0])
|
||||||
}
|
}
|
||||||
return getPath(val, keys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFromMap(val interface{}, key string) (interface{}, error) {
|
func getFromMap(val interface{}, key string) (interface{}, error) {
|
||||||
|
@ -2,20 +2,20 @@ package jsoniter
|
|||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
|
// ReadObject is a implemented iterator for json
|
||||||
func (iter *Iterator) ReadObject() (ret string) {
|
func (iter *Iterator) ReadObject() (ret string) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch c {
|
switch c {
|
||||||
case 'n': {
|
case 'n':
|
||||||
iter.skipUntilBreak()
|
iter.skipUntilBreak()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return "" // null
|
return "" // null
|
||||||
}
|
case '{':
|
||||||
case '{': {
|
|
||||||
c = iter.nextToken()
|
c = iter.nextToken()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
@ -27,16 +27,15 @@ func (iter *Iterator) ReadObject() (ret string) {
|
|||||||
iter.unreadByte()
|
iter.unreadByte()
|
||||||
return iter.readObjectField()
|
return iter.readObjectField()
|
||||||
default:
|
default:
|
||||||
iter.ReportError("ReadObject", `expect " after {`)
|
iter.reportError("ReadObject", `expect " after {`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
case ',':
|
case ',':
|
||||||
return iter.readObjectField()
|
return iter.readObjectField()
|
||||||
case '}':
|
case '}':
|
||||||
return "" // end of object
|
return "" // end of object
|
||||||
default:
|
default:
|
||||||
iter.ReportError("ReadObject", `expect { or , or } or n`)
|
iter.reportError("ReadObject", `expect { or , or } or n`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,7 +50,7 @@ func (iter *Iterator) readObjectStart() bool {
|
|||||||
iter.unreadByte()
|
iter.unreadByte()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
iter.ReportError("readObjectStart", "expect { ")
|
iter.reportError("readObjectStart", "expect { ")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,20 +58,20 @@ func (iter *Iterator) readObjectField() (ret string) {
|
|||||||
str := iter.readStringAsBytes()
|
str := iter.readStringAsBytes()
|
||||||
if iter.skipWhitespacesWithoutLoadMore() {
|
if iter.skipWhitespacesWithoutLoadMore() {
|
||||||
if ret == "" {
|
if ret == "" {
|
||||||
ret = string(str);
|
ret = string(str)
|
||||||
}
|
}
|
||||||
if !iter.loadMore() {
|
if !iter.loadMore() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if iter.buf[iter.head] != ':' {
|
if iter.buf[iter.head] != ':' {
|
||||||
iter.ReportError("ReadObject", "expect : after object field")
|
iter.reportError("ReadObject", "expect : after object field")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
iter.head++
|
iter.head++
|
||||||
if iter.skipWhitespacesWithoutLoadMore() {
|
if iter.skipWhitespacesWithoutLoadMore() {
|
||||||
if ret == "" {
|
if ret == "" {
|
||||||
ret = string(str);
|
ret = string(str)
|
||||||
}
|
}
|
||||||
if !iter.loadMore() {
|
if !iter.loadMore() {
|
||||||
return
|
return
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
|
||||||
"sync/atomic"
|
|
||||||
"strings"
|
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -20,6 +20,7 @@ Reflection on value is avoided as we can, as the reflect.Value itself will alloc
|
|||||||
For a simple struct binding, it will be reflect.Value free and allocation free
|
For a simple struct binding, it will be reflect.Value free and allocation free
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Decoder works like a father class for sub-type decoders
|
||||||
type Decoder interface {
|
type Decoder interface {
|
||||||
decode(ptr unsafe.Pointer, iter *Iterator)
|
decode(ptr unsafe.Pointer, iter *Iterator)
|
||||||
}
|
}
|
||||||
@ -129,7 +130,6 @@ func (decoder *interfaceDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
*((*interface{})(ptr)) = iter.ReadAny().Get()
|
*((*interface{})(ptr)) = iter.ReadAny().Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type anyDecoder struct {
|
type anyDecoder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ type stringNumberDecoder struct {
|
|||||||
func (decoder *stringNumberDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (decoder *stringNumberDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
if c != '"' {
|
if c != '"' {
|
||||||
iter.ReportError("stringNumberDecoder", `expect "`)
|
iter.reportError("stringNumberDecoder", `expect "`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
decoder.elemDecoder.decode(ptr, iter)
|
decoder.elemDecoder.decode(ptr, iter)
|
||||||
@ -153,7 +153,7 @@ func (decoder *stringNumberDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
}
|
}
|
||||||
c = iter.readByte()
|
c = iter.readByte()
|
||||||
if c != '"' {
|
if c != '"' {
|
||||||
iter.ReportError("stringNumberDecoder", `expect "`)
|
iter.reportError("stringNumberDecoder", `expect "`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ type optionalDecoder struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (decoder *optionalDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (decoder *optionalDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNull() {
|
if iter.ReadNil() {
|
||||||
*((*unsafe.Pointer)(ptr)) = nil
|
*((*unsafe.Pointer)(ptr)) = nil
|
||||||
} else {
|
} else {
|
||||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||||
@ -180,7 +180,7 @@ func (decoder *optionalDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type generalStructDecoder struct {
|
type generalStructDecoder struct {
|
||||||
type_ reflect.Type
|
typ reflect.Type
|
||||||
fields map[string]*structFieldDecoder
|
fields map[string]*structFieldDecoder
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,23 +194,23 @@ func (decoder *generalStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if iter.Error != nil && iter.Error != io.EOF {
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type skipDecoder struct {
|
type skipDecoder struct {
|
||||||
type_ reflect.Type
|
typ reflect.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
iter.Skip()
|
iter.Skip()
|
||||||
if iter.Error != nil && iter.Error != io.EOF {
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type oneFieldStructDecoder struct {
|
type oneFieldStructDecoder struct {
|
||||||
type_ reflect.Type
|
typ reflect.Type
|
||||||
fieldName string
|
fieldName string
|
||||||
fieldDecoder *structFieldDecoder
|
fieldDecoder *structFieldDecoder
|
||||||
}
|
}
|
||||||
@ -224,12 +224,12 @@ func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if iter.Error != nil && iter.Error != io.EOF {
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type twoFieldsStructDecoder struct {
|
type twoFieldsStructDecoder struct {
|
||||||
type_ reflect.Type
|
typ reflect.Type
|
||||||
fieldName1 string
|
fieldName1 string
|
||||||
fieldDecoder1 *structFieldDecoder
|
fieldDecoder1 *structFieldDecoder
|
||||||
fieldName2 string
|
fieldName2 string
|
||||||
@ -248,12 +248,12 @@ func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if iter.Error != nil && iter.Error != io.EOF {
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type threeFieldsStructDecoder struct {
|
type threeFieldsStructDecoder struct {
|
||||||
type_ reflect.Type
|
typ reflect.Type
|
||||||
fieldName1 string
|
fieldName1 string
|
||||||
fieldDecoder1 *structFieldDecoder
|
fieldDecoder1 *structFieldDecoder
|
||||||
fieldName2 string
|
fieldName2 string
|
||||||
@ -276,12 +276,12 @@ func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if iter.Error != nil && iter.Error != io.EOF {
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type fourFieldsStructDecoder struct {
|
type fourFieldsStructDecoder struct {
|
||||||
type_ reflect.Type
|
typ reflect.Type
|
||||||
fieldName1 string
|
fieldName1 string
|
||||||
fieldDecoder1 *structFieldDecoder
|
fieldDecoder1 *structFieldDecoder
|
||||||
fieldName2 string
|
fieldName2 string
|
||||||
@ -325,7 +325,7 @@ func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterato
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if iter.Error != nil && iter.Error != io.EOF {
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,29 +494,33 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)
|
type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)
|
||||||
type ExtensionFunc func(type_ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc)
|
type ExtensionFunc func(typ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc)
|
||||||
|
|
||||||
type funcDecoder struct {
|
type funcDecoder struct {
|
||||||
func_ DecoderFunc
|
fun DecoderFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (decoder *funcDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (decoder *funcDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
decoder.func_(ptr, iter)
|
decoder.fun(ptr, iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterTypeDecoder(type_ string, func_ DecoderFunc) {
|
// RegisterTypeDecoder can register a type for json object
|
||||||
typeDecoders[type_] = &funcDecoder{func_}
|
func RegisterTypeDecoder(typ string, fun DecoderFunc) {
|
||||||
|
typeDecoders[typ] = &funcDecoder{fun}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterFieldDecoder(type_ string, field string, func_ DecoderFunc) {
|
// RegisterFieldDecoder can register a type for json field
|
||||||
fieldDecoders[fmt.Sprintf("%s/%s", type_, field)] = &funcDecoder{func_}
|
func RegisterFieldDecoder(typ string, field string, fun DecoderFunc) {
|
||||||
|
fieldDecoders[fmt.Sprintf("%s/%s", typ, field)] = &funcDecoder{fun}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterExtension can register a custom extension
|
||||||
func RegisterExtension(extension ExtensionFunc) {
|
func RegisterExtension(extension ExtensionFunc) {
|
||||||
extensions = append(extensions, extension)
|
extensions = append(extensions, extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClearDecoders() {
|
// CleanDecoders cleans decoders registered
|
||||||
|
func CleanDecoders() {
|
||||||
typeDecoders = map[string]Decoder{}
|
typeDecoders = map[string]Decoder{}
|
||||||
fieldDecoders = map[string]Decoder{}
|
fieldDecoders = map[string]Decoder{}
|
||||||
}
|
}
|
||||||
@ -527,6 +531,7 @@ type emptyInterface struct {
|
|||||||
word unsafe.Pointer
|
word unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadAny converts a json object in a Iterator instance to Any
|
||||||
func (iter *Iterator) ReadAny() (ret *Any) {
|
func (iter *Iterator) ReadAny() (ret *Any) {
|
||||||
valueType := iter.WhatIsNext()
|
valueType := iter.WhatIsNext()
|
||||||
switch valueType {
|
switch valueType {
|
||||||
@ -540,7 +545,7 @@ func (iter *Iterator) ReadAny() (ret *Any) {
|
|||||||
return MakeAny(iter.ReadBool())
|
return MakeAny(iter.ReadBool())
|
||||||
case Array:
|
case Array:
|
||||||
val := []interface{}{}
|
val := []interface{}{}
|
||||||
for (iter.ReadArray()) {
|
for iter.ReadArray() {
|
||||||
element := iter.ReadAny()
|
element := iter.ReadAny()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
@ -559,20 +564,18 @@ func (iter *Iterator) ReadAny() (ret *Any) {
|
|||||||
}
|
}
|
||||||
return MakeAny(val)
|
return MakeAny(val)
|
||||||
default:
|
default:
|
||||||
iter.ReportError("ReadAny", fmt.Sprintf("unexpected value type: %v", valueType))
|
iter.reportError("ReadAny", fmt.Sprintf("unexpected value type: %v", valueType))
|
||||||
return MakeAny(nil)
|
return MakeAny(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (iter *Iterator) readNumber() (ret *Any) {
|
func (iter *Iterator) readNumber() (ret *Any) {
|
||||||
strBuf := [8]byte{}
|
strBuf := [8]byte{}
|
||||||
str := strBuf[0:0]
|
str := strBuf[0:0]
|
||||||
hasMore := true
|
hasMore := true
|
||||||
foundFloat := false
|
foundFloat := false
|
||||||
foundNegative := false
|
foundNegative := false
|
||||||
for(hasMore) {
|
for hasMore {
|
||||||
for i := iter.head; i < iter.tail; i++ {
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
c := iter.buf[i]
|
c := iter.buf[i]
|
||||||
switch c {
|
switch c {
|
||||||
@ -630,12 +633,13 @@ func (iter *Iterator) readNumber() (ret *Any) {
|
|||||||
return MakeAny(val)
|
return MakeAny(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read converts an Iterator instance into go interface, same as json.Unmarshal
|
||||||
func (iter *Iterator) Read(obj interface{}) {
|
func (iter *Iterator) Read(obj interface{}) {
|
||||||
type_ := reflect.TypeOf(obj)
|
typ := reflect.TypeOf(obj)
|
||||||
cacheKey := type_.Elem()
|
cacheKey := typ.Elem()
|
||||||
cachedDecoder := getDecoderFromCache(cacheKey)
|
cachedDecoder := getDecoderFromCache(cacheKey)
|
||||||
if cachedDecoder == nil {
|
if cachedDecoder == nil {
|
||||||
decoder, err := decoderOfType(type_)
|
decoder, err := decoderOfType(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
iter.Error = err
|
iter.Error = err
|
||||||
return
|
return
|
||||||
@ -656,17 +660,17 @@ func (p prefix) addTo(decoder Decoder, err error) (Decoder, error) {
|
|||||||
return decoder, err
|
return decoder, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func decoderOfType(type_ reflect.Type) (Decoder, error) {
|
func decoderOfType(typ reflect.Type) (Decoder, error) {
|
||||||
switch type_.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
return prefix("ptr").addTo(decoderOfPtr(type_.Elem()))
|
return prefix("ptr").addTo(decoderOfPtr(typ.Elem()))
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("expect ptr")
|
return nil, errors.New("expect ptr")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decoderOfPtr(type_ reflect.Type) (Decoder, error) {
|
func decoderOfPtr(typ reflect.Type) (Decoder, error) {
|
||||||
typeName := type_.String()
|
typeName := typ.String()
|
||||||
if typeName == "jsoniter.Any" {
|
if typeName == "jsoniter.Any" {
|
||||||
return &anyDecoder{}, nil
|
return &anyDecoder{}, nil
|
||||||
}
|
}
|
||||||
@ -674,7 +678,7 @@ func decoderOfPtr(type_ reflect.Type) (Decoder, error) {
|
|||||||
if typeDecoder != nil {
|
if typeDecoder != nil {
|
||||||
return typeDecoder, nil
|
return typeDecoder, nil
|
||||||
}
|
}
|
||||||
switch type_.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return &stringDecoder{}, nil
|
return &stringDecoder{}, nil
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
@ -706,39 +710,39 @@ func decoderOfPtr(type_ reflect.Type) (Decoder, error) {
|
|||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
return &interfaceDecoder{}, nil
|
return &interfaceDecoder{}, nil
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return decoderOfStruct(type_)
|
return decoderOfStruct(typ)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return prefix("[slice]").addTo(decoderOfSlice(type_))
|
return prefix("[slice]").addTo(decoderOfSlice(typ))
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
return prefix("[map]").addTo(decoderOfMap(type_))
|
return prefix("[map]").addTo(decoderOfMap(typ))
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
return prefix("[optional]").addTo(decoderOfOptional(type_.Elem()))
|
return prefix("[optional]").addTo(decoderOfOptional(typ.Elem()))
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported type: %v", type_)
|
return nil, fmt.Errorf("unsupported type: %v", typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decoderOfOptional(type_ reflect.Type) (Decoder, error) {
|
func decoderOfOptional(typ reflect.Type) (Decoder, error) {
|
||||||
decoder, err := decoderOfPtr(type_)
|
decoder, err := decoderOfPtr(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &optionalDecoder{type_, decoder}, nil
|
return &optionalDecoder{typ, decoder}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
|
func decoderOfStruct(typ reflect.Type) (Decoder, error) {
|
||||||
fields := map[string]*structFieldDecoder{}
|
fields := map[string]*structFieldDecoder{}
|
||||||
for i := 0; i < type_.NumField(); i++ {
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
field := type_.Field(i)
|
field := typ.Field(i)
|
||||||
fieldDecoderKey := fmt.Sprintf("%s/%s", type_.String(), field.Name)
|
fieldDecoderKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
|
||||||
var fieldNames []string
|
var fieldNames []string
|
||||||
for _, extension := range extensions {
|
for _, extension := range extensions {
|
||||||
alternativeFieldNames, func_ := extension(type_, &field)
|
alternativeFieldNames, fun := extension(typ, &field)
|
||||||
if alternativeFieldNames != nil {
|
if alternativeFieldNames != nil {
|
||||||
fieldNames = alternativeFieldNames
|
fieldNames = alternativeFieldNames
|
||||||
}
|
}
|
||||||
if func_ != nil {
|
if fun != nil {
|
||||||
fieldDecoders[fieldDecoderKey] = &funcDecoder{func_}
|
fieldDecoders[fieldDecoderKey] = &funcDecoder{fun}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decoder := fieldDecoders[fieldDecoderKey]
|
decoder := fieldDecoders[fieldDecoderKey]
|
||||||
@ -771,10 +775,10 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
|
|||||||
}
|
}
|
||||||
switch len(fields) {
|
switch len(fields) {
|
||||||
case 0:
|
case 0:
|
||||||
return &skipDecoder{type_}, nil
|
return &skipDecoder{typ}, nil
|
||||||
case 1:
|
case 1:
|
||||||
for fieldName, fieldDecoder := range fields {
|
for fieldName, fieldDecoder := range fields {
|
||||||
return &oneFieldStructDecoder{type_, fieldName, fieldDecoder}, nil
|
return &oneFieldStructDecoder{typ, fieldName, fieldDecoder}, nil
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
var fieldName1 string
|
var fieldName1 string
|
||||||
@ -790,7 +794,7 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
|
|||||||
fieldDecoder2 = fieldDecoder
|
fieldDecoder2 = fieldDecoder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &twoFieldsStructDecoder{type_, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil
|
return &twoFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil
|
||||||
case 3:
|
case 3:
|
||||||
var fieldName1 string
|
var fieldName1 string
|
||||||
var fieldName2 string
|
var fieldName2 string
|
||||||
@ -810,7 +814,7 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
|
|||||||
fieldDecoder3 = fieldDecoder
|
fieldDecoder3 = fieldDecoder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &threeFieldsStructDecoder{type_,
|
return &threeFieldsStructDecoder{typ,
|
||||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
|
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
|
||||||
case 4:
|
case 4:
|
||||||
var fieldName1 string
|
var fieldName1 string
|
||||||
@ -836,26 +840,26 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
|
|||||||
fieldDecoder4 = fieldDecoder
|
fieldDecoder4 = fieldDecoder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &fourFieldsStructDecoder{type_,
|
return &fourFieldsStructDecoder{typ,
|
||||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||||
fieldName4, fieldDecoder4}, nil
|
fieldName4, fieldDecoder4}, nil
|
||||||
}
|
}
|
||||||
return &generalStructDecoder{type_, fields}, nil
|
return &generalStructDecoder{typ, fields}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decoderOfSlice(type_ reflect.Type) (Decoder, error) {
|
func decoderOfSlice(typ reflect.Type) (Decoder, error) {
|
||||||
decoder, err := decoderOfPtr(type_.Elem())
|
decoder, err := decoderOfPtr(typ.Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &sliceDecoder{type_, type_.Elem(), decoder}, nil
|
return &sliceDecoder{typ, typ.Elem(), decoder}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decoderOfMap(type_ reflect.Type) (Decoder, error) {
|
func decoderOfMap(typ reflect.Type) (Decoder, error) {
|
||||||
decoder, err := decoderOfPtr(type_.Elem())
|
decoder, err := decoderOfPtr(typ.Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
mapInterface := reflect.New(type_).Interface()
|
mapInterface := reflect.New(typ).Interface()
|
||||||
return &mapDecoder{type_, type_.Elem(), decoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
|
return &mapDecoder{typ, typ.Elem(), decoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
|
||||||
}
|
}
|
||||||
|
173
jsoniter.go
173
jsoniter.go
@ -1,12 +1,12 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"fmt"
|
|
||||||
"unicode/utf16"
|
|
||||||
"strconv"
|
|
||||||
"unsafe"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"unicode/utf16"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValueType int
|
type ValueType int
|
||||||
@ -30,37 +30,38 @@ func init() {
|
|||||||
digits[i] = 255
|
digits[i] = 255
|
||||||
}
|
}
|
||||||
for i := '0'; i <= '9'; i++ {
|
for i := '0'; i <= '9'; i++ {
|
||||||
digits[i] = byte(i - '0');
|
digits[i] = byte(i - '0')
|
||||||
}
|
}
|
||||||
for i := 'a'; i <= 'f'; i++ {
|
for i := 'a'; i <= 'f'; i++ {
|
||||||
digits[i] = byte((i - 'a') + 10);
|
digits[i] = byte((i - 'a') + 10)
|
||||||
}
|
}
|
||||||
for i := 'A'; i <= 'F'; i++ {
|
for i := 'A'; i <= 'F'; i++ {
|
||||||
digits[i] = byte((i - 'A') + 10);
|
digits[i] = byte((i - 'A') + 10)
|
||||||
}
|
}
|
||||||
valueTypes = make([]ValueType, 256)
|
valueTypes = make([]ValueType, 256)
|
||||||
for i := 0; i < len(valueTypes); i++ {
|
for i := 0; i < len(valueTypes); i++ {
|
||||||
valueTypes[i] = Invalid
|
valueTypes[i] = Invalid
|
||||||
}
|
}
|
||||||
valueTypes['"'] = String;
|
valueTypes['"'] = String
|
||||||
valueTypes['-'] = Number;
|
valueTypes['-'] = Number
|
||||||
valueTypes['0'] = Number;
|
valueTypes['0'] = Number
|
||||||
valueTypes['1'] = Number;
|
valueTypes['1'] = Number
|
||||||
valueTypes['2'] = Number;
|
valueTypes['2'] = Number
|
||||||
valueTypes['3'] = Number;
|
valueTypes['3'] = Number
|
||||||
valueTypes['4'] = Number;
|
valueTypes['4'] = Number
|
||||||
valueTypes['5'] = Number;
|
valueTypes['5'] = Number
|
||||||
valueTypes['6'] = Number;
|
valueTypes['6'] = Number
|
||||||
valueTypes['7'] = Number;
|
valueTypes['7'] = Number
|
||||||
valueTypes['8'] = Number;
|
valueTypes['8'] = Number
|
||||||
valueTypes['9'] = Number;
|
valueTypes['9'] = Number
|
||||||
valueTypes['t'] = Bool;
|
valueTypes['t'] = Bool
|
||||||
valueTypes['f'] = Bool;
|
valueTypes['f'] = Bool
|
||||||
valueTypes['n'] = Null;
|
valueTypes['n'] = Null
|
||||||
valueTypes['['] = Array;
|
valueTypes['['] = Array
|
||||||
valueTypes['{'] = Object;
|
valueTypes['{'] = Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterator is a fast and flexible JSON parser
|
||||||
type Iterator struct {
|
type Iterator struct {
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
buf []byte
|
buf []byte
|
||||||
@ -69,6 +70,7 @@ type Iterator struct {
|
|||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create creates an empty Iterator instance
|
||||||
func Create() *Iterator {
|
func Create() *Iterator {
|
||||||
return &Iterator{
|
return &Iterator{
|
||||||
reader: nil,
|
reader: nil,
|
||||||
@ -78,6 +80,7 @@ func Create() *Iterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse parses a json buffer in io.Reader into an Iterator instance
|
||||||
func Parse(reader io.Reader, bufSize int) *Iterator {
|
func Parse(reader io.Reader, bufSize int) *Iterator {
|
||||||
return &Iterator{
|
return &Iterator{
|
||||||
reader: reader,
|
reader: reader,
|
||||||
@ -87,6 +90,7 @@ func Parse(reader io.Reader, bufSize int) *Iterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseBytes parses a json byte slice into an Iterator instance
|
||||||
func ParseBytes(input []byte) *Iterator {
|
func ParseBytes(input []byte) *Iterator {
|
||||||
return &Iterator{
|
return &Iterator{
|
||||||
reader: nil,
|
reader: nil,
|
||||||
@ -96,10 +100,12 @@ func ParseBytes(input []byte) *Iterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseString parses a json string into an Iterator instance
|
||||||
func ParseString(input string) *Iterator {
|
func ParseString(input string) *Iterator {
|
||||||
return ParseBytes([]byte(input))
|
return ParseBytes([]byte(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset can reset an Iterator instance for another json buffer in io.Reader
|
||||||
func (iter *Iterator) Reset(reader io.Reader) *Iterator {
|
func (iter *Iterator) Reset(reader io.Reader) *Iterator {
|
||||||
iter.reader = reader
|
iter.reader = reader
|
||||||
iter.head = 0
|
iter.head = 0
|
||||||
@ -107,6 +113,7 @@ func (iter *Iterator) Reset(reader io.Reader) *Iterator {
|
|||||||
return iter
|
return iter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetBytes can reset an Iterator instance for another json byte slice
|
||||||
func (iter *Iterator) ResetBytes(input []byte) *Iterator {
|
func (iter *Iterator) ResetBytes(input []byte) *Iterator {
|
||||||
iter.reader = nil
|
iter.reader = nil
|
||||||
iter.Error = nil
|
iter.Error = nil
|
||||||
@ -116,10 +123,11 @@ func (iter *Iterator) ResetBytes(input []byte) *Iterator {
|
|||||||
return iter
|
return iter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WhatIsNext gets ValueType of relatively next json object
|
||||||
func (iter *Iterator) WhatIsNext() ValueType {
|
func (iter *Iterator) WhatIsNext() ValueType {
|
||||||
valueType := valueTypes[iter.nextToken()];
|
valueType := valueTypes[iter.nextToken()]
|
||||||
iter.unreadByte();
|
iter.unreadByte()
|
||||||
return valueType;
|
return valueType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool {
|
func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool {
|
||||||
@ -153,7 +161,7 @@ func (iter *Iterator) nextToken() byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) ReportError(operation string, msg string) {
|
func (iter *Iterator) reportError(operation string, msg string) {
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -165,6 +173,7 @@ func (iter *Iterator) ReportError(operation string, msg string) {
|
|||||||
string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
|
string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CurrentBuffer gets current buffer as string
|
||||||
func (iter *Iterator) CurrentBuffer() string {
|
func (iter *Iterator) CurrentBuffer() string {
|
||||||
peekStart := iter.head - 10
|
peekStart := iter.head - 10
|
||||||
if peekStart < 0 {
|
if peekStart < 0 {
|
||||||
@ -180,9 +189,8 @@ func (iter *Iterator) readByte() (ret byte) {
|
|||||||
ret = iter.buf[iter.head]
|
ret = iter.buf[iter.head]
|
||||||
iter.head++
|
iter.head++
|
||||||
return ret
|
return ret
|
||||||
} else {
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
ret = iter.buf[iter.head]
|
ret = iter.buf[iter.head]
|
||||||
iter.head++
|
iter.head++
|
||||||
@ -200,9 +208,6 @@ func (iter *Iterator) loadMore() bool {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
iter.Error = err
|
iter.Error = err
|
||||||
return false
|
return false
|
||||||
} else {
|
|
||||||
// n == 0, err == nil is not EOF
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iter.head = 0
|
iter.head = 0
|
||||||
@ -214,10 +219,10 @@ func (iter *Iterator) loadMore() bool {
|
|||||||
|
|
||||||
func (iter *Iterator) unreadByte() {
|
func (iter *Iterator) unreadByte() {
|
||||||
if iter.head == 0 {
|
if iter.head == 0 {
|
||||||
iter.ReportError("unreadByte", "unread too many bytes")
|
iter.reportError("unreadByte", "unread too many bytes")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
iter.head -= 1
|
iter.head--
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,46 +231,51 @@ const cutoffUint64 = maxUint64 / 10 + 1
|
|||||||
const maxUint32 = (1<<32 - 1)
|
const maxUint32 = (1<<32 - 1)
|
||||||
const cutoffUint32 = maxUint32/10 + 1
|
const cutoffUint32 = maxUint32/10 + 1
|
||||||
|
|
||||||
|
// ReadUint reads a json object as Uint
|
||||||
func (iter *Iterator) ReadUint() (ret uint) {
|
func (iter *Iterator) ReadUint() (ret uint) {
|
||||||
val := iter.ReadUint64()
|
val := iter.ReadUint64()
|
||||||
converted := uint(val)
|
converted := uint(val)
|
||||||
if uint64(converted) != val {
|
if uint64(converted) != val {
|
||||||
iter.ReportError("ReadUint", "int overflow")
|
iter.reportError("ReadUint", "int overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadUint8 reads a json object as Uint8
|
||||||
func (iter *Iterator) ReadUint8() (ret uint8) {
|
func (iter *Iterator) ReadUint8() (ret uint8) {
|
||||||
val := iter.ReadUint64()
|
val := iter.ReadUint64()
|
||||||
converted := uint8(val)
|
converted := uint8(val)
|
||||||
if uint64(converted) != val {
|
if uint64(converted) != val {
|
||||||
iter.ReportError("ReadUint8", "int overflow")
|
iter.reportError("ReadUint8", "int overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadUint16 reads a json object as Uint16
|
||||||
func (iter *Iterator) ReadUint16() (ret uint16) {
|
func (iter *Iterator) ReadUint16() (ret uint16) {
|
||||||
val := iter.ReadUint64()
|
val := iter.ReadUint64()
|
||||||
converted := uint16(val)
|
converted := uint16(val)
|
||||||
if uint64(converted) != val {
|
if uint64(converted) != val {
|
||||||
iter.ReportError("ReadUint16", "int overflow")
|
iter.reportError("ReadUint16", "int overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadUint32 reads a json object as Uint32
|
||||||
func (iter *Iterator) ReadUint32() (ret uint32) {
|
func (iter *Iterator) ReadUint32() (ret uint32) {
|
||||||
val := iter.ReadUint64()
|
val := iter.ReadUint64()
|
||||||
converted := uint32(val)
|
converted := uint32(val)
|
||||||
if uint64(converted) != val {
|
if uint64(converted) != val {
|
||||||
iter.ReportError("ReadUint32", "int overflow")
|
iter.reportError("ReadUint32", "int overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadUint64 reads a json object as Uint64
|
||||||
func (iter *Iterator) ReadUint64() (ret uint64) {
|
func (iter *Iterator) ReadUint64() (ret uint64) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
v := digits[c]
|
v := digits[c]
|
||||||
@ -273,12 +283,12 @@ func (iter *Iterator) ReadUint64() (ret uint64) {
|
|||||||
return 0 // single zero
|
return 0 // single zero
|
||||||
}
|
}
|
||||||
if v == 255 {
|
if v == 255 {
|
||||||
iter.ReportError("ReadUint64", "unexpected character")
|
iter.reportError("ReadUint64", "unexpected character")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
if ret >= cutoffUint64 {
|
if ret >= cutoffUint64 {
|
||||||
iter.ReportError("ReadUint64", "overflow")
|
iter.reportError("ReadUint64", "overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret = ret*10 + uint64(v)
|
ret = ret*10 + uint64(v)
|
||||||
@ -292,46 +302,51 @@ func (iter *Iterator) ReadUint64() (ret uint64) {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadInt reads a json object as Int
|
||||||
func (iter *Iterator) ReadInt() (ret int) {
|
func (iter *Iterator) ReadInt() (ret int) {
|
||||||
val := iter.ReadInt64()
|
val := iter.ReadInt64()
|
||||||
converted := int(val)
|
converted := int(val)
|
||||||
if int64(converted) != val {
|
if int64(converted) != val {
|
||||||
iter.ReportError("ReadInt", "int overflow")
|
iter.reportError("ReadInt", "int overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadInt8 reads a json object as Int8
|
||||||
func (iter *Iterator) ReadInt8() (ret int8) {
|
func (iter *Iterator) ReadInt8() (ret int8) {
|
||||||
val := iter.ReadInt64()
|
val := iter.ReadInt64()
|
||||||
converted := int8(val)
|
converted := int8(val)
|
||||||
if int64(converted) != val {
|
if int64(converted) != val {
|
||||||
iter.ReportError("ReadInt8", "int overflow")
|
iter.reportError("ReadInt8", "int overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadInt16 reads a json object as Int16
|
||||||
func (iter *Iterator) ReadInt16() (ret int16) {
|
func (iter *Iterator) ReadInt16() (ret int16) {
|
||||||
val := iter.ReadInt64()
|
val := iter.ReadInt64()
|
||||||
converted := int16(val)
|
converted := int16(val)
|
||||||
if int64(converted) != val {
|
if int64(converted) != val {
|
||||||
iter.ReportError("ReadInt16", "int overflow")
|
iter.reportError("ReadInt16", "int overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadInt32 reads a json object as Int32
|
||||||
func (iter *Iterator) ReadInt32() (ret int32) {
|
func (iter *Iterator) ReadInt32() (ret int32) {
|
||||||
val := iter.ReadInt64()
|
val := iter.ReadInt64()
|
||||||
converted := int32(val)
|
converted := int32(val)
|
||||||
if int64(converted) != val {
|
if int64(converted) != val {
|
||||||
iter.ReportError("ReadInt32", "int overflow")
|
iter.reportError("ReadInt32", "int overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadInt64 reads a json object as Int64
|
||||||
func (iter *Iterator) ReadInt64() (ret int64) {
|
func (iter *Iterator) ReadInt64() (ret int64) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
@ -342,18 +357,17 @@ func (iter *Iterator) ReadInt64() (ret int64) {
|
|||||||
if c == '-' {
|
if c == '-' {
|
||||||
n := iter.ReadUint64()
|
n := iter.ReadUint64()
|
||||||
return -int64(n)
|
return -int64(n)
|
||||||
} else {
|
}
|
||||||
iter.unreadByte()
|
iter.unreadByte()
|
||||||
n := iter.ReadUint64()
|
n := iter.ReadUint64()
|
||||||
return int64(n)
|
return int64(n)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// ReadString reads a json object as String
|
||||||
func (iter *Iterator) ReadString() (ret string) {
|
func (iter *Iterator) ReadString() (ret string) {
|
||||||
return string(iter.readStringAsBytes())
|
return string(iter.readStringAsBytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (iter *Iterator) readStringAsBytes() (ret []byte) {
|
func (iter *Iterator) readStringAsBytes() (ret []byte) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
if c == '"' {
|
if c == '"' {
|
||||||
@ -370,7 +384,7 @@ func (iter *Iterator) readStringAsBytes() (ret []byte) {
|
|||||||
iter.skipUntilBreak()
|
iter.skipUntilBreak()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
iter.ReportError("ReadString", `expects " or n`)
|
iter.reportError("ReadString", `expects " or n`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +413,7 @@ func (iter *Iterator) readStringAsBytesSlowPath() (ret []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if c != '\\' {
|
if c != '\\' {
|
||||||
iter.ReportError("ReadString",
|
iter.reportError("ReadString",
|
||||||
`expects \u after utf16 surrogate, but \ not found`)
|
`expects \u after utf16 surrogate, but \ not found`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -408,7 +422,7 @@ func (iter *Iterator) readStringAsBytesSlowPath() (ret []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if c != 'u' {
|
if c != 'u' {
|
||||||
iter.ReportError("ReadString",
|
iter.reportError("ReadString",
|
||||||
`expects \u after utf16 surrogate, but \u not found`)
|
`expects \u after utf16 surrogate, but \u not found`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -438,7 +452,7 @@ func (iter *Iterator) readStringAsBytesSlowPath() (ret []byte) {
|
|||||||
case 't':
|
case 't':
|
||||||
str = append(str, '\t')
|
str = append(str, '\t')
|
||||||
default:
|
default:
|
||||||
iter.ReportError("ReadString",
|
iter.reportError("ReadString",
|
||||||
`invalid escape char after \`)
|
`invalid escape char after \`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -455,20 +469,20 @@ func (iter *Iterator) readU4() (ret rune) {
|
|||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (c >= '0' && c <= '9') {
|
if c >= '0' && c <= '9' {
|
||||||
if ret >= cutoffUint32 {
|
if ret >= cutoffUint32 {
|
||||||
iter.ReportError("readU4", "overflow")
|
iter.reportError("readU4", "overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret = ret*16 + rune(c-'0')
|
ret = ret*16 + rune(c-'0')
|
||||||
} else if ((c >= 'a' && c <= 'f') ) {
|
} else if c >= 'a' && c <= 'f' {
|
||||||
if ret >= cutoffUint32 {
|
if ret >= cutoffUint32 {
|
||||||
iter.ReportError("readU4", "overflow")
|
iter.reportError("readU4", "overflow")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret = ret*16 + rune(c-'a'+10)
|
ret = ret*16 + rune(c-'a'+10)
|
||||||
} else {
|
} else {
|
||||||
iter.ReportError("readU4", "expects 0~9 or a~f")
|
iter.reportError("readU4", "expects 0~9 or a~f")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,42 +540,42 @@ func appendRune(p []byte, r rune) []byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadArray reads a json object as Array
|
||||||
func (iter *Iterator) ReadArray() (ret bool) {
|
func (iter *Iterator) ReadArray() (ret bool) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch c {
|
switch c {
|
||||||
case 'n': {
|
case 'n':
|
||||||
iter.skipUntilBreak()
|
iter.skipUntilBreak()
|
||||||
return false // null
|
return false // null
|
||||||
}
|
case '[':
|
||||||
case '[': {
|
|
||||||
c = iter.nextToken()
|
c = iter.nextToken()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if c == ']' {
|
if c == ']' {
|
||||||
return false
|
return false
|
||||||
} else {
|
}
|
||||||
iter.unreadByte()
|
iter.unreadByte()
|
||||||
return true
|
return true
|
||||||
}
|
case ']':
|
||||||
}
|
return false
|
||||||
case ']': return false
|
|
||||||
case ',':
|
case ',':
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
iter.ReportError("ReadArray", "expect [ or , or ] or n, but found: " + string([]byte{c}))
|
iter.reportError("ReadArray", "expect [ or , or ] or n, but found: "+string([]byte{c}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadFloat32 reads a json object as Float32
|
||||||
func (iter *Iterator) ReadFloat32() (ret float32) {
|
func (iter *Iterator) ReadFloat32() (ret float32) {
|
||||||
strBuf := [8]byte{}
|
strBuf := [8]byte{}
|
||||||
str := strBuf[0:0]
|
str := strBuf[0:0]
|
||||||
hasMore := true
|
hasMore := true
|
||||||
for(hasMore) {
|
for hasMore {
|
||||||
for i := iter.head; i < iter.tail; i++ {
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
c := iter.buf[i]
|
c := iter.buf[i]
|
||||||
switch c {
|
switch c {
|
||||||
@ -590,11 +604,12 @@ func (iter *Iterator) ReadFloat32() (ret float32) {
|
|||||||
return float32(val)
|
return float32(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadFloat64 reads a json object as Float64
|
||||||
func (iter *Iterator) ReadFloat64() (ret float64) {
|
func (iter *Iterator) ReadFloat64() (ret float64) {
|
||||||
strBuf := [8]byte{}
|
strBuf := [8]byte{}
|
||||||
str := strBuf[0:0]
|
str := strBuf[0:0]
|
||||||
hasMore := true
|
hasMore := true
|
||||||
for(hasMore) {
|
for hasMore {
|
||||||
for i := iter.head; i < iter.tail; i++ {
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
c := iter.buf[i]
|
c := iter.buf[i]
|
||||||
switch c {
|
switch c {
|
||||||
@ -623,6 +638,7 @@ func (iter *Iterator) ReadFloat64() (ret float64) {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadBool reads a json object as Bool
|
||||||
func (iter *Iterator) ReadBool() (ret bool) {
|
func (iter *Iterator) ReadBool() (ret bool) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
@ -636,11 +652,12 @@ func (iter *Iterator) ReadBool() (ret bool) {
|
|||||||
iter.skipUntilBreak()
|
iter.skipUntilBreak()
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
iter.ReportError("ReadBool", "expect t or f")
|
iter.reportError("ReadBool", "expect t or f")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadBase64 reads a json object as Base64 in byte slice
|
||||||
func (iter *Iterator) ReadBase64() (ret []byte) {
|
func (iter *Iterator) ReadBase64() (ret []byte) {
|
||||||
src := iter.readStringAsBytes()
|
src := iter.readStringAsBytes()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
@ -656,7 +673,9 @@ func (iter *Iterator) ReadBase64() (ret []byte) {
|
|||||||
return ret[:n]
|
return ret[:n]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) ReadNull() (ret bool) {
|
// ReadNil reads a json object as nil and
|
||||||
|
// returns whether it's a nil or not
|
||||||
|
func (iter *Iterator) ReadNil() (ret bool) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
if c == 'n' {
|
if c == 'n' {
|
||||||
iter.skipUntilBreak()
|
iter.skipUntilBreak()
|
||||||
@ -666,6 +685,7 @@ func (iter *Iterator) ReadNull() (ret bool) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip skips a json object and positions to relatively the next json object
|
||||||
func (iter *Iterator) Skip() {
|
func (iter *Iterator) Skip() {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
switch c {
|
switch c {
|
||||||
@ -678,7 +698,7 @@ func (iter *Iterator) Skip() {
|
|||||||
case '{':
|
case '{':
|
||||||
iter.skipObject()
|
iter.skipObject()
|
||||||
default:
|
default:
|
||||||
iter.ReportError("Skip", fmt.Sprintf("do not know how to skip: %v", c))
|
iter.reportError("Skip", fmt.Sprintf("do not know how to skip: %v", c))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -700,7 +720,6 @@ func (iter *Iterator) skipString() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// adapted from: https://github.com/buger/jsonparser/blob/master/parser.go
|
// adapted from: https://github.com/buger/jsonparser/blob/master/parser.go
|
||||||
// Tries to find the end of string
|
// Tries to find the end of string
|
||||||
// Support if string contains escaped quote symbols.
|
// Support if string contains escaped quote symbols.
|
||||||
@ -711,7 +730,7 @@ func (iter *Iterator) findStringEnd() (int, bool) {
|
|||||||
if c == '"' {
|
if c == '"' {
|
||||||
if !escaped {
|
if !escaped {
|
||||||
return i + 1, false
|
return i + 1, false
|
||||||
} else {
|
}
|
||||||
j := i - 1
|
j := i - 1
|
||||||
for {
|
for {
|
||||||
if j < iter.head || iter.buf[j] != '\\' {
|
if j < iter.head || iter.buf[j] != '\\' {
|
||||||
@ -727,7 +746,6 @@ func (iter *Iterator) findStringEnd() (int, bool) {
|
|||||||
}
|
}
|
||||||
j--
|
j--
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if c == '\\' {
|
} else if c == '\\' {
|
||||||
escaped = true
|
escaped = true
|
||||||
}
|
}
|
||||||
@ -751,7 +769,6 @@ func (iter *Iterator) findStringEnd() (int, bool) {
|
|||||||
return -1, true // end with \
|
return -1, true // end with \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (iter *Iterator) findStringEndWithoutEscape() int {
|
func (iter *Iterator) findStringEndWithoutEscape() int {
|
||||||
for i := iter.head; i < iter.tail; i++ {
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
c := iter.buf[i]
|
c := iter.buf[i]
|
||||||
@ -785,7 +802,7 @@ func (iter *Iterator) skipArray() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!iter.loadMore()) {
|
if !iter.loadMore() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -812,7 +829,7 @@ func (iter *Iterator) skipObject() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!iter.loadMore()) {
|
if !iter.loadMore() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -829,7 +846,7 @@ func (iter *Iterator) skipUntilBreak() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!iter.loadMore()) {
|
if !iter.loadMore() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_read_string_as_any(t *testing.T) {
|
func Test_read_string_as_any(t *testing.T) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_empty_array(t *testing.T) {
|
func Test_empty_array(t *testing.T) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_read_base64(t *testing.T) {
|
func Test_read_base64(t *testing.T) {
|
||||||
@ -12,7 +12,6 @@ func Test_read_base64(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func Test_bad_case(t *testing.T) {
|
func Test_bad_case(t *testing.T) {
|
||||||
// field := *(*string)(unsafe.Pointer(&str))
|
// field := *(*string)(unsafe.Pointer(&str))
|
||||||
// caused this issue
|
// caused this issue
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"strconv"
|
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_customize_type_decoder(t *testing.T) {
|
func Test_customize_type_decoder(t *testing.T) {
|
||||||
@ -17,7 +17,7 @@ func Test_customize_type_decoder(t *testing.T) {
|
|||||||
}
|
}
|
||||||
*((*time.Time)(ptr)) = t
|
*((*time.Time)(ptr)) = t
|
||||||
})
|
})
|
||||||
defer ClearDecoders()
|
defer CleanDecoders()
|
||||||
val := time.Time{}
|
val := time.Time{}
|
||||||
err := Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val)
|
err := Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -37,7 +37,7 @@ func Test_customize_field_decoder(t *testing.T) {
|
|||||||
RegisterFieldDecoder("jsoniter.Tom", "field1", func(ptr unsafe.Pointer, iter *Iterator) {
|
RegisterFieldDecoder("jsoniter.Tom", "field1", func(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
|
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
|
||||||
})
|
})
|
||||||
defer ClearDecoders()
|
defer CleanDecoders()
|
||||||
tom := Tom{}
|
tom := Tom{}
|
||||||
err := Unmarshal([]byte(`{"field1": 100}`), &tom)
|
err := Unmarshal([]byte(`{"field1": 100}`), &tom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -51,7 +51,7 @@ type TestObject1 struct {
|
|||||||
|
|
||||||
func Test_customize_field_by_extension(t *testing.T) {
|
func Test_customize_field_by_extension(t *testing.T) {
|
||||||
RegisterExtension(func(type_ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc) {
|
RegisterExtension(func(type_ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc) {
|
||||||
if (type_.String() == "jsoniter.TestObject1" && field.Name == "field1") {
|
if type_.String() == "jsoniter.TestObject1" && field.Name == "field1" {
|
||||||
return []string{"field-1"}, func(ptr unsafe.Pointer, iter *Iterator) {
|
return []string{"field-1"}, func(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
|
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_bind_api_demo(t *testing.T) {
|
func Test_bind_api_demo(t *testing.T) {
|
||||||
@ -39,7 +39,7 @@ func Test_deep_nested_any_api(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
userId int
|
userID int
|
||||||
name string
|
name string
|
||||||
tags []string
|
tags []string
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ func Test_iterator_and_bind_api(t *testing.T) {
|
|||||||
iter := ParseString(`[123, {"name": "taowen", "tags": ["crazy", "hacker"]}]`)
|
iter := ParseString(`[123, {"name": "taowen", "tags": ["crazy", "hacker"]}]`)
|
||||||
user := User{}
|
user := User{}
|
||||||
iter.ReadArray()
|
iter.ReadArray()
|
||||||
user.userId = iter.ReadInt()
|
user.userID = iter.ReadInt()
|
||||||
iter.ReadArray()
|
iter.ReadArray()
|
||||||
iter.Read(&user)
|
iter.Read(&user)
|
||||||
iter.ReadArray() // array end
|
iter.ReadArray() // array end
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"io"
|
"io"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_string_end(t *testing.T) {
|
func Test_string_end(t *testing.T) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_float64_0(t *testing.T) {
|
func Test_float64_0(t *testing.T) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_uint64_0(t *testing.T) {
|
func Test_uint64_0(t *testing.T) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_read_by_one(t *testing.T) {
|
func Test_read_by_one(t *testing.T) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"os"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
//func Test_large_file(t *testing.T) {
|
//func Test_large_file(t *testing.T) {
|
||||||
@ -23,7 +23,6 @@ import (
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
func Benchmark_jsoniter_large_file(b *testing.B) {
|
func Benchmark_jsoniter_large_file(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"reflect"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_read_map(t *testing.T) {
|
func Test_read_map(t *testing.T) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"reflect"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Level1 struct {
|
type Level1 struct {
|
||||||
@ -28,14 +28,14 @@ func Test_nested(t *testing.T) {
|
|||||||
case "world":
|
case "world":
|
||||||
l2.World = iter.ReadString()
|
l2.World = iter.ReadString()
|
||||||
default:
|
default:
|
||||||
iter.ReportError("bind l2", "unexpected field: " + l2Field)
|
iter.reportError("bind l2", "unexpected field: "+l2Field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l2Array = append(l2Array, l2)
|
l2Array = append(l2Array, l2)
|
||||||
}
|
}
|
||||||
l1.Hello = l2Array
|
l1.Hello = l2Array
|
||||||
default:
|
default:
|
||||||
iter.ReportError("bind l1", "unexpected field: " + l1Field)
|
iter.reportError("bind l1", "unexpected field: "+l1Field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(l1, Level1{
|
if !reflect.DeepEqual(l1, Level1{
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
func Test_null(t *testing.T) {
|
func Test_null(t *testing.T) {
|
||||||
iter := ParseString(`null`)
|
iter := ParseString(`null`)
|
||||||
if iter.ReadNull() != true {
|
if iter.ReadNil() != true {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_empty_object(t *testing.T) {
|
func Test_empty_object(t *testing.T) {
|
||||||
@ -61,7 +61,7 @@ func Test_two_field(t *testing.T) {
|
|||||||
case "field2":
|
case "field2":
|
||||||
iter.ReadInt64()
|
iter.ReadInt64()
|
||||||
default:
|
default:
|
||||||
iter.ReportError("bind object", "unexpected field")
|
iter.reportError("bind object", "unexpected field")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ func Benchmark_jsoniter_object(b *testing.B) {
|
|||||||
case "field2":
|
case "field2":
|
||||||
obj.Field2 = iter.ReadUint64()
|
obj.Field2 = iter.ReadUint64()
|
||||||
default:
|
default:
|
||||||
iter.ReportError("bind object", "unexpected field")
|
iter.reportError("bind object", "unexpected field")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"fmt"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -162,15 +162,15 @@ type StructOfString struct {
|
|||||||
|
|
||||||
func Test_reflect_struct_string(t *testing.T) {
|
func Test_reflect_struct_string(t *testing.T) {
|
||||||
iter := ParseString(`{"field1": "hello", "field2": "world"}`)
|
iter := ParseString(`{"field1": "hello", "field2": "world"}`)
|
||||||
struct_ := StructOfString{}
|
Struct := StructOfString{}
|
||||||
iter.Read(&struct_)
|
iter.Read(&Struct)
|
||||||
if struct_.field1 != "hello" {
|
if Struct.field1 != "hello" {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(struct_.field1)
|
t.Fatal(Struct.field1)
|
||||||
}
|
}
|
||||||
if struct_.field2 != "world" {
|
if Struct.field2 != "world" {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(struct_.field1)
|
t.Fatal(Struct.field2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,39 +181,39 @@ type StructOfStringPtr struct {
|
|||||||
|
|
||||||
func Test_reflect_struct_string_ptr(t *testing.T) {
|
func Test_reflect_struct_string_ptr(t *testing.T) {
|
||||||
iter := ParseString(`{"field1": null, "field2": "world"}`)
|
iter := ParseString(`{"field1": null, "field2": "world"}`)
|
||||||
struct_ := StructOfStringPtr{}
|
Struct := StructOfStringPtr{}
|
||||||
iter.Read(&struct_)
|
iter.Read(&Struct)
|
||||||
if struct_.field1 != nil {
|
if Struct.field1 != nil {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(struct_.field1)
|
t.Fatal(Struct.field1)
|
||||||
}
|
}
|
||||||
if *struct_.field2 != "world" {
|
if *Struct.field2 != "world" {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(struct_.field2)
|
t.Fatal(Struct.field2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type StructOfTag struct {
|
type StructOfTag struct {
|
||||||
field1 string `json:"field-1"`
|
Field1 string `json:"field-1"`
|
||||||
field2 string `json:"-"`
|
Field2 string `json:"-"`
|
||||||
field3 int `json:",string"`
|
Field3 int `json:",string"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_reflect_struct_tag_field(t *testing.T) {
|
func Test_reflect_struct_tag_field(t *testing.T) {
|
||||||
iter := ParseString(`{"field-1": "hello", "field2": "", "field3": "100"}`)
|
iter := ParseString(`{"field-1": "hello", "field2": "", "Field3": "100"}`)
|
||||||
struct_ := StructOfTag{field2: "world"}
|
Struct := StructOfTag{Field2: "world"}
|
||||||
iter.Read(&struct_)
|
iter.Read(&Struct)
|
||||||
if struct_.field1 != "hello" {
|
if Struct.Field1 != "hello" {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(struct_.field1)
|
t.Fatal(Struct.Field1)
|
||||||
}
|
}
|
||||||
if struct_.field2 != "world" {
|
if Struct.Field2 != "world" {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(struct_.field2)
|
t.Fatal(Struct.Field2)
|
||||||
}
|
}
|
||||||
if struct_.field3 != 100 {
|
if Struct.Field3 != 100 {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(struct_.field3)
|
t.Fatal(Struct.Field3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ func Test_reflect_large_slice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
if slice[8] != 9 {
|
if slice[8] != 9 {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(slice[1])
|
t.Fatal(slice[8])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ func Test_reflect_nested(t *testing.T) {
|
|||||||
}
|
}
|
||||||
if slice[2].field2 != "world" {
|
if slice[2].field2 != "world" {
|
||||||
fmt.Println(iter.Error)
|
fmt.Println(iter.Error)
|
||||||
t.Fatal(slice[1])
|
t.Fatal(slice[2])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ func Test_reflect_base64(t *testing.T) {
|
|||||||
RegisterTypeDecoder("[]uint8", func(ptr unsafe.Pointer, iter *Iterator) {
|
RegisterTypeDecoder("[]uint8", func(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
*((*[]byte)(ptr)) = iter.ReadBase64()
|
*((*[]byte)(ptr)) = iter.ReadBase64()
|
||||||
})
|
})
|
||||||
defer ClearDecoders()
|
defer CleanDecoders()
|
||||||
iter.Read(&val)
|
iter.Read(&val)
|
||||||
if "abc" != string(val) {
|
if "abc" != string(val) {
|
||||||
t.Fatal(string(val))
|
t.Fatal(string(val))
|
||||||
@ -289,22 +289,22 @@ func Test_reflect_base64(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type StructOfTagOne struct {
|
type StructOfTagOne struct {
|
||||||
field1 string `json:"field1"`
|
Field1 string `json:"field1"`
|
||||||
field2 string `json:"field2"`
|
Field2 string `json:"field2"`
|
||||||
field3 int `json:"field3,string"`
|
Field3 int `json:"field3,string"`
|
||||||
field4 int `json:"field4,string"`
|
Field4 int `json:"field4,string"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Benchmark_jsoniter_reflect(b *testing.B) {
|
func Benchmark_jsoniter_reflect(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
iter := Create()
|
iter := Create()
|
||||||
struct_ := &StructOfTagOne{}
|
Struct := &StructOfTagOne{}
|
||||||
//var struct_ *StructOfTagOne
|
//var Struct *StructOfTagOne
|
||||||
input := []byte(`{"field3": "100", "field4": "100"}`)
|
input := []byte(`{"field3": "100", "field4": "100"}`)
|
||||||
//input := []byte(`null`)
|
//input := []byte(`null`)
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
iter.ResetBytes(input)
|
iter.ResetBytes(input)
|
||||||
iter.Read(&struct_)
|
iter.Read(&Struct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,9 +316,9 @@ func Benchmark_jsoniter_direct(b *testing.B) {
|
|||||||
//for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
//for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
||||||
// switch field {
|
// switch field {
|
||||||
// case "field1":
|
// case "field1":
|
||||||
// struct_.field1 = iter.ReadString()
|
// struct_.Field1 = iter.ReadString()
|
||||||
// case "field2":
|
// case "field2":
|
||||||
// struct_.field2 = iter.ReadString()
|
// struct_.Field2 = iter.ReadString()
|
||||||
// default:
|
// default:
|
||||||
// iter.Skip()
|
// iter.Skip()
|
||||||
// }
|
// }
|
||||||
@ -334,8 +334,8 @@ func Benchmark_jsoniter_direct(b *testing.B) {
|
|||||||
func Benchmark_json_reflect(b *testing.B) {
|
func Benchmark_json_reflect(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
struct_ := StructOfTagOne{}
|
Struct := StructOfTagOne{}
|
||||||
json.Unmarshal([]byte(`{"field3": "100"}`), &struct_)
|
json.Unmarshal([]byte(`{"field3": "100"}`), &Struct)
|
||||||
//array := make([]string, 0, 2)
|
//array := make([]string, 0, 2)
|
||||||
//json.Unmarshal([]byte(`["hello", "world"]`), &array)
|
//json.Unmarshal([]byte(`["hello", "world"]`), &array)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func Test_skip_number(t *testing.T) {
|
func Test_skip_number(t *testing.T) {
|
||||||
iter := ParseString(`[-0.12, "b"]`)
|
iter := ParseString(`[-0.12, "b"]`)
|
||||||
iter.ReadArray()
|
iter.ReadArray()
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_string_empty(t *testing.T) {
|
func Test_string_empty(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user