added ForEach function

This commit is contained in:
Josh Baker 2016-11-30 10:50:59 -07:00
parent 86b1b630e4
commit 62892351c5
3 changed files with 111 additions and 0 deletions

View File

@ -185,6 +185,20 @@ name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`)
println(name.String()) // prints "Elliotte" println(name.String()) // prints "Elliotte"
``` ```
## Iterate through an object or array
The `ForEach` function allows for quickly iterating through an object or array.
The key and value are passed to the iterator function for objects.
Only the value is passed for arrays.
Returning `false` from an iterator will stop iteration.
```go
result := gjson.Get(json, "programmers")
result.ForEach(func(key, value Result) bool{
println(value.String())
return true // keep iterating
})
```
## Simple Parse and Get ## Simple Parse and Get

View File

@ -152,6 +152,66 @@ func (t Result) Array() []Result {
return r.a return r.a
} }
// ForEach iterates through values.
// If the result represents a non-existent value, then no values will be iterated.
// If the result is an Object, the iterator will pass the key and value of each item.
// If the result is an Array, the iterator will only pass the value of each item.
// If the result is not a JSON array or object, the iterator will pass back one value equal to the result.
func (t Result) ForEach(iterator func(key, value Result) bool) {
if !t.Exists() {
return
}
if t.Type != JSON {
iterator(Result{}, t)
return
}
json := t.Raw
var keys bool
var i int
var key, value Result
for ; i < len(json); i++ {
if json[i] == '{' {
i++
key.Type = String
keys = true
break
} else if json[i] == '[' {
i++
break
}
if json[i] > ' ' {
return
}
}
var str string
var vesc bool
var ok bool
for ; i < len(json); i++ {
if keys {
if json[i] != '"' {
continue
}
i, str, vesc, ok = parseString(json, i+1)
if !ok {
return
}
if vesc {
key.Str = unescape(str[1 : len(str)-1])
} else {
key.Str = str[1 : len(str)-1]
}
key.Raw = str
}
i, value, ok = parseAny(json, i, true)
if !ok {
return
}
if !iterator(key, value) {
return
}
}
}
// Map returns back an map of values. The result should be a JSON array. // Map returns back an map of values. The result should be a JSON array.
func (t Result) Map() map[string]Result { func (t Result) Map() map[string]Result {
if t.Type != JSON { if t.Type != JSON {

View File

@ -163,6 +163,43 @@ func TestBasic(t *testing.T) {
if mtok.String() != `["Brett","Elliotte"]` { if mtok.String() != `["Brett","Elliotte"]` {
t.Fatalf("expected %v, got %v", `["Brett","Elliotte"]`, mtok.String()) t.Fatalf("expected %v, got %v", `["Brett","Elliotte"]`, mtok.String())
} }
mtok = get(basicJSON, `loggy.programmers`)
var count int
mtok.ForEach(func(key, value Result) bool {
if key.Exists() {
t.Fatalf("expected %v, got %v", false, key.Exists())
}
count++
if count == 3 {
return false
}
if count == 1 {
i := 0
value.ForEach(func(key, value Result) bool {
switch i {
case 0:
if key.String() != "firstName" || value.String() != "Brett" {
t.Fatalf("expected %v/%v got %v/%v", "firstName", "Brett", key.String(), value.String())
}
case 1:
if key.String() != "lastName" || value.String() != "McLaughlin" {
t.Fatalf("expected %v/%v got %v/%v", "lastName", "McLaughlin", key.String(), value.String())
}
case 2:
if key.String() != "email" || value.String() != "aaaa" {
t.Fatalf("expected %v/%v got %v/%v", "email", "aaaa", key.String(), value.String())
}
}
i++
return true
})
}
return true
})
if count != 3 {
t.Fatalf("expected %v, got %v", 3, count)
}
mtok = get(basicJSON, `loggy.programmers.#[age=101].firstName`) mtok = get(basicJSON, `loggy.programmers.#[age=101].firstName`)
if mtok.String() != "1002.3" { if mtok.String() != "1002.3" {
t.Fatalf("expected %v, got %v", "1002.3", mtok.String()) t.Fatalf("expected %v, got %v", "1002.3", mtok.String())