Skip to content

Commit cac9cd1

Browse files
authored
fix: object.ForEach now continues the loop after consuming a skipped value (#92)
1 parent 53771bd commit cac9cd1

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

parsed_object.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ func (o *Object) ForEach(fn func(key []byte, i Iter), onlyKeys map[string]struct
169169
if t == TypeNone {
170170
return nil
171171
}
172+
continue
172173
}
173174
}
174175

parsed_object_test.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package simdjson
33
import (
44
"fmt"
55
"log"
6+
"reflect"
67
"testing"
78
)
89

@@ -130,6 +131,119 @@ func TestObject_FindPath(t *testing.T) {
130131
}
131132
}
132133

134+
func TestObject_ForEach(t *testing.T) {
135+
if !SupportedCPU() {
136+
t.SkipNow()
137+
}
138+
input := `{
139+
"key1": "value1",
140+
"key2": "value2",
141+
"key3": "value3",
142+
"key4": "value4",
143+
"key5": "value5",
144+
"key6": "value6",
145+
"key7": "value7",
146+
"key8": "value8",
147+
"key9": "value9",
148+
"key10": "value10"
149+
}`
150+
tests := []struct {
151+
name string
152+
onlyKeys []string
153+
want map[string]string
154+
}{
155+
{
156+
name: "all-keys",
157+
onlyKeys: nil,
158+
want: map[string]string{
159+
"key1": "value1",
160+
"key2": "value2",
161+
"key3": "value3",
162+
"key4": "value4",
163+
"key5": "value5",
164+
"key6": "value6",
165+
"key7": "value7",
166+
"key8": "value8",
167+
"key9": "value9",
168+
"key10": "value10",
169+
},
170+
},
171+
{
172+
name: "some-keys",
173+
onlyKeys: []string{"key1", "key3"},
174+
want: map[string]string{
175+
"key1": "value1",
176+
"key3": "value3"},
177+
},
178+
{
179+
name: "sparse-keys",
180+
onlyKeys: []string{
181+
"key1", "key3", "key5", "key7", "key9"},
182+
want: map[string]string{
183+
"key1": "value1",
184+
"key3": "value3",
185+
"key5": "value5",
186+
"key7": "value7",
187+
"key9": "value9",
188+
},
189+
},
190+
{
191+
name: "sparse-keys",
192+
onlyKeys: []string{"key1", "key2", "key3", "key9", "key10"},
193+
want: map[string]string{
194+
"key1": "value1",
195+
"key2": "value2",
196+
"key3": "value3",
197+
"key9": "value9",
198+
"key10": "value10",
199+
},
200+
},
201+
{
202+
name: "no-keys",
203+
onlyKeys: []string{"key20"},
204+
want: map[string]string{},
205+
},
206+
}
207+
for _, tt := range tests {
208+
pj, err := Parse([]byte(input), nil)
209+
if err != nil {
210+
t.Fatal(err)
211+
}
212+
t.Run(tt.name, func(t *testing.T) {
213+
filtered := make(map[string]string)
214+
var onlyKeys map[string]struct{}
215+
if len(tt.onlyKeys) > 0 {
216+
onlyKeys = make(map[string]struct{}, len(tt.onlyKeys))
217+
for _, key := range tt.onlyKeys {
218+
onlyKeys[key] = struct{}{}
219+
}
220+
}
221+
i := pj.Iter()
222+
var elem Iter
223+
ty, err := i.AdvanceIter(&elem)
224+
225+
if err != nil || ty != TypeRoot {
226+
t.Fatal(err)
227+
}
228+
_ = elem.AdvanceInto()
229+
obj, err := elem.Object(nil)
230+
if err != nil {
231+
t.Fatal(err)
232+
}
233+
err = obj.ForEach(func(key []byte, i Iter) {
234+
value, _ := i.StringCvt()
235+
filtered[string(key)] = value
236+
}, onlyKeys)
237+
if err != nil {
238+
t.Fatal(err)
239+
}
240+
if !reflect.DeepEqual(tt.want, filtered) {
241+
t.Errorf("want %v\ngot %v\n", tt.want, filtered)
242+
}
243+
})
244+
}
245+
}
246+
133247
func ExampleObject_FindPath() {
134248
if !SupportedCPU() {
135249
// Fake it

0 commit comments

Comments
 (0)