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