Skip to content

Commit 90d9533

Browse files
authored
Merge pull request #96 from verytable/feature/provide-decoded-array-index
add Index() method to Decoder
2 parents 106fcfa + 75d85cb commit 90d9533

File tree

4 files changed

+114
-9
lines changed

4 files changed

+114
-9
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,20 @@ func (c ChannelArray) UnmarshalJSONArray(dec *gojay.Decoder) error {
286286
}
287287
```
288288

289+
Example of implementation with an array:
290+
```go
291+
type testArray [3]string
292+
// implement UnmarshalerJSONArray
293+
func (a *testArray) UnmarshalJSONArray(dec *Decoder) error {
294+
var str string
295+
if err := dec.String(&str); err != nil {
296+
return err
297+
}
298+
a[dec.Index()] = str
299+
return nil
300+
}
301+
```
302+
289303
### Other types
290304
To decode other types (string, int, int32, int64, uint32, uint64, float, booleans), you don't need to implement any interface.
291305

decode.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,16 @@ type UnmarshalerJSONArray interface {
235235

236236
// A Decoder reads and decodes JSON values from an input stream.
237237
type Decoder struct {
238-
r io.Reader
239-
data []byte
240-
err error
241-
isPooled byte
242-
called byte
243-
child byte
244-
cursor int
245-
length int
246-
keysDone int
238+
r io.Reader
239+
data []byte
240+
err error
241+
isPooled byte
242+
called byte
243+
child byte
244+
cursor int
245+
length int
246+
keysDone int
247+
arrayIndex int
247248
}
248249

249250
// Decode reads the next JSON-encoded value from the decoder's input (io.Reader) and stores it in the value pointed to by v.

decode_array.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ func (dec *Decoder) DecodeArray(v UnmarshalerJSONArray) error {
1616
return err
1717
}
1818
func (dec *Decoder) decodeArray(arr UnmarshalerJSONArray) (int, error) {
19+
// remember last array index in case of nested arrays
20+
lastArrayIndex := dec.arrayIndex
21+
dec.arrayIndex = 0
22+
defer func() {
23+
dec.arrayIndex = lastArrayIndex
24+
}()
1925
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
2026
switch dec.data[dec.cursor] {
2127
case ' ', '\n', '\t', '\r', ',':
@@ -34,6 +40,7 @@ func (dec *Decoder) decodeArray(arr UnmarshalerJSONArray) (int, error) {
3440
if err != nil {
3541
return 0, err
3642
}
43+
dec.arrayIndex++
3744
}
3845
return 0, dec.raiseInvalidJSONErr(dec.cursor)
3946
case 'n':
@@ -60,6 +67,12 @@ func (dec *Decoder) decodeArray(arr UnmarshalerJSONArray) (int, error) {
6067
return 0, dec.raiseInvalidJSONErr(dec.cursor)
6168
}
6269
func (dec *Decoder) decodeArrayNull(v interface{}) (int, error) {
70+
// remember last array index in case of nested arrays
71+
lastArrayIndex := dec.arrayIndex
72+
dec.arrayIndex = 0
73+
defer func() {
74+
dec.arrayIndex = lastArrayIndex
75+
}()
6376
vv := reflect.ValueOf(v)
6477
vvt := vv.Type()
6578
if vvt.Kind() != reflect.Ptr || vvt.Elem().Kind() != reflect.Ptr {
@@ -96,6 +109,7 @@ func (dec *Decoder) decodeArrayNull(v interface{}) (int, error) {
96109
if err != nil {
97110
return 0, err
98111
}
112+
dec.arrayIndex++
99113
}
100114
return 0, dec.raiseInvalidJSONErr(dec.cursor)
101115
case 'n':
@@ -226,3 +240,8 @@ func (dec *Decoder) ArrayNull(v interface{}) error {
226240
dec.called |= 1
227241
return nil
228242
}
243+
244+
// Index returns the index of an array being decoded.
245+
func (dec *Decoder) Index() int {
246+
return dec.arrayIndex
247+
}

decode_array_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,3 +627,74 @@ func TestDecoderArrayFunc(t *testing.T) {
627627
var f DecodeArrayFunc
628628
assert.True(t, f.IsNil())
629629
}
630+
631+
type testArrayStrings [3]string
632+
633+
func (a *testArrayStrings) UnmarshalJSONArray(dec *Decoder) error {
634+
var str string
635+
if err := dec.String(&str); err != nil {
636+
return err
637+
}
638+
a[dec.Index()] = str
639+
return nil
640+
}
641+
642+
func TestArrayStrings(t *testing.T) {
643+
data := []byte(`["a", "b", "c"]`)
644+
arr := testArrayStrings{}
645+
err := Unmarshal(data, &arr)
646+
assert.Nil(t, err, "err must be nil")
647+
assert.Equal(t, "a", arr[0], "arr[0] must be equal to 'a'")
648+
assert.Equal(t, "b", arr[1], "arr[1] must be equal to 'b'")
649+
assert.Equal(t, "c", arr[2], "arr[2] must be equal to 'c'")
650+
}
651+
652+
type testSliceArraysStrings struct {
653+
arrays []testArrayStrings
654+
t *testing.T
655+
}
656+
657+
func (s *testSliceArraysStrings) UnmarshalJSONArray(dec *Decoder) error {
658+
var a testArrayStrings
659+
assert.Equal(s.t, len(s.arrays), dec.Index(), "decoded array index must be equal to current slice len")
660+
if err := dec.AddArray(&a); err != nil {
661+
return err
662+
}
663+
assert.Equal(s.t, len(s.arrays), dec.Index(), "decoded array index must be equal to current slice len")
664+
s.arrays = append(s.arrays, a)
665+
return nil
666+
}
667+
668+
func TestIndex(t *testing.T) {
669+
testCases := []struct {
670+
name string
671+
json string
672+
expectedResult []testArrayStrings
673+
}{
674+
{
675+
name: "basic-test",
676+
json: `[["a","b","c"],["1","2","3"],["x","y","z"]]`,
677+
expectedResult: []testArrayStrings{{"a", "b", "c"}, {"1", "2", "3"}, {"x", "y", "z"}},
678+
},
679+
{
680+
name: "basic-test-null",
681+
json: `[["a","b","c"],null,["x","y","z"]]`,
682+
expectedResult: []testArrayStrings{{"a", "b", "c"}, {"", "", ""}, {"x", "y", "z"}},
683+
},
684+
}
685+
686+
for _, testCase := range testCases {
687+
t.Run(testCase.name, func(t *testing.T) {
688+
s := make([]testArrayStrings, 0)
689+
dec := BorrowDecoder(strings.NewReader(testCase.json))
690+
defer dec.Release()
691+
a := testSliceArraysStrings{arrays: s, t: t}
692+
err := dec.Decode(&a)
693+
assert.Nil(t, err, "err should be nil")
694+
assert.Zero(t, dec.Index(), "Index() must return zero after decoding")
695+
for k, v := range testCase.expectedResult {
696+
assert.Equal(t, v, a.arrays[k], "value at given index should be the same as expected results")
697+
}
698+
})
699+
}
700+
}

0 commit comments

Comments
 (0)