Skip to content

Commit 7d98e94

Browse files
author
Tao Wen
committed
implement ReadInterface
1 parent b30c597 commit 7d98e94

File tree

4 files changed

+131
-60
lines changed

4 files changed

+131
-60
lines changed

iter.go

-60
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,14 @@ import (
44
"fmt"
55
)
66

7-
// ValueType the type for JSON element
8-
type ValueType int
9-
107
type RawMessage []byte
118

12-
const (
13-
// InvalidValue invalid JSON element
14-
InvalidValue ValueType = iota
15-
// StringValue JSON element "string"
16-
StringValue
17-
// NumberValue JSON element 100 or 0.10
18-
NumberValue
19-
// NullValue JSON element null
20-
NullValue
21-
// BoolValue JSON element true or false
22-
BoolValue
23-
// ArrayValue JSON element []
24-
ArrayValue
25-
// ObjectValue JSON element {}
26-
ObjectValue
27-
)
289
const uint32SafeToMultiply10 = uint32(0xffffffff)/10 - 1
2910
const uint64SafeToMultiple10 = uint64(0xffffffffffffffff)/10 - 1
3011
const maxFloat64 = 1<<53 - 1
3112

3213
var pow10 []uint64
3314
var hexDigits []byte
34-
var valueTypes []ValueType
3515

3616
func init() {
3717
pow10 = []uint64{1, 10, 100, 1000, 10000, 100000, 1000000}
@@ -48,27 +28,6 @@ func init() {
4828
for i := 'A'; i <= 'F'; i++ {
4929
hexDigits[i] = byte((i - 'A') + 10)
5030
}
51-
valueTypes = make([]ValueType, 256)
52-
for i := 0; i < len(valueTypes); i++ {
53-
valueTypes[i] = InvalidValue
54-
}
55-
valueTypes['"'] = StringValue
56-
valueTypes['-'] = NumberValue
57-
valueTypes['0'] = NumberValue
58-
valueTypes['1'] = NumberValue
59-
valueTypes['2'] = NumberValue
60-
valueTypes['3'] = NumberValue
61-
valueTypes['4'] = NumberValue
62-
valueTypes['5'] = NumberValue
63-
valueTypes['6'] = NumberValue
64-
valueTypes['7'] = NumberValue
65-
valueTypes['8'] = NumberValue
66-
valueTypes['9'] = NumberValue
67-
valueTypes['t'] = BoolValue
68-
valueTypes['f'] = BoolValue
69-
valueTypes['n'] = NullValue
70-
valueTypes['['] = ArrayValue
71-
valueTypes['{'] = ObjectValue
7231
}
7332

7433
// Iterator is a io.Reader like object, with JSON specific read functions.
@@ -87,13 +46,6 @@ func ParseBytes(input []byte) *Iterator {
8746
}
8847
}
8948

90-
// WhatIsNext gets ValueType of relatively next json element
91-
func (iter *Iterator) WhatIsNext() ValueType {
92-
valueType := valueTypes[iter.nextToken()]
93-
iter.unreadByte()
94-
return valueType
95-
}
96-
9749
func (iter *Iterator) skipWhitespaces() {
9850
for i := iter.head; i < len(iter.buf); i++ {
9951
c := iter.buf[i]
@@ -107,18 +59,6 @@ func (iter *Iterator) skipWhitespaces() {
10759
iter.head = len(iter.buf)
10860
}
10961

110-
func (iter *Iterator) isObjectEnd() bool {
111-
c := iter.nextToken()
112-
if c == ',' {
113-
return false
114-
}
115-
if c == '}' {
116-
return true
117-
}
118-
iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c}))
119-
return true
120-
}
121-
12262
// ReportError record a error in iterator instance with current position.
12363
func (iter *Iterator) ReportError(operation string, msg string) error {
12464
if iter.Error != nil {

iter_interface.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package jsoniter
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
func (iter *Iterator) ReadInterface(out *interface{}) (ret error) {
8+
c := iter.nextToken()
9+
switch c {
10+
case '"':
11+
var val string
12+
ret = iter.readString(&val)
13+
if ret == nil {
14+
*out = val
15+
}
16+
return
17+
case 'n':
18+
return iter.skipThreeBytes('u', 'l', 'l') // null
19+
case 't':
20+
ret = iter.skipThreeBytes('r', 'u', 'e') // true
21+
if ret == nil {
22+
*out = true
23+
}
24+
return
25+
case 'f':
26+
ret = iter.skipFourBytes('a', 'l', 's', 'e') // false
27+
if ret == nil {
28+
*out = false
29+
}
30+
return
31+
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
32+
iter.unreadByte()
33+
var val float64
34+
ret = iter.ReadFloat64(&val)
35+
if ret == nil {
36+
*out = val
37+
}
38+
return
39+
case '[':
40+
var val = make([]interface{}, 0)
41+
c := iter.nextToken()
42+
if c == ']' {
43+
*out = val
44+
return
45+
}
46+
iter.unreadByte()
47+
more := true
48+
for more {
49+
var elem interface{}
50+
iter.ReadInterface(&elem)
51+
val = append(val, elem)
52+
more = iter.ReadArrayMore()
53+
}
54+
*out = val
55+
return iter.Error
56+
case '{':
57+
val := make(map[string]interface{}, 0)
58+
*out = val
59+
c := iter.nextToken()
60+
if c == ']' {
61+
return
62+
}
63+
iter.unreadByte()
64+
more := true
65+
for more {
66+
k := iter.ReadObjectField()
67+
var v interface{}
68+
iter.ReadInterface(&v)
69+
val[k] = v
70+
more = iter.ReadObjectMore()
71+
}
72+
return iter.Error
73+
default:
74+
return iter.ReportError("ReadInterface", fmt.Sprintf("unexpected character: %v", c))
75+
}
76+
}

iter_str.go

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ func (iter *Iterator) ReadString(out *string) error {
1717
iter.skip(c)
1818
return err
1919
}
20+
return iter.readString(out)
21+
}
22+
23+
func (iter *Iterator) readString(out *string) error {
2024
for i := iter.head; i < len(iter.buf); i++ {
2125
c := iter.buf[i]
2226
if c == '"' {

iter_tests/interface_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package iter_tests
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"testing"
7+
8+
jsoniter "github.com/json-iterator/tinygo"
9+
)
10+
11+
func readEmptyInterface(input string, expectedValue interface{}) {
12+
iter := jsoniter.ParseBytes([]byte(input))
13+
var val interface{}
14+
iter.ReadInterface(&val)
15+
if val != expectedValue {
16+
panic(fmt.Errorf("expect %s, acutal %s", expectedValue, val))
17+
}
18+
}
19+
20+
func Test_read_empty_interface(t *testing.T) {
21+
readEmptyInterface("true", true)
22+
readEmptyInterface("false", false)
23+
readEmptyInterface("100", float64(100))
24+
readEmptyInterface(`"hello"`, "hello")
25+
}
26+
27+
func Test_read_array_as_empty_interface(t *testing.T) {
28+
iter := jsoniter.ParseBytes([]byte(`[1,true,"hello"]`))
29+
var val interface{}
30+
iter.ReadInterface(&val)
31+
bytes, err := json.Marshal(val)
32+
if err != nil {
33+
t.Fatal()
34+
}
35+
if string(bytes) != `[1,true,"hello"]` {
36+
t.Fatal()
37+
}
38+
}
39+
40+
func Test_read_object_as_empty_interface(t *testing.T) {
41+
iter := jsoniter.ParseBytes([]byte(`{"hello":"world"}`))
42+
var val interface{}
43+
iter.ReadInterface(&val)
44+
bytes, err := json.Marshal(val)
45+
if err != nil {
46+
t.Fatal()
47+
}
48+
if string(bytes) != `{"hello":"world"}` {
49+
t.Fatal()
50+
}
51+
}

0 commit comments

Comments
 (0)