Open lamados opened 1 year ago
There's nothing built into gjson that does this using a path.
This is probably the most efficient way I can think of.
package main
import "github.com/tidwall/gjson"
func sliceJSONArray(res gjson.Result, start, end int) gjson.Result {
var raw []byte
var i, j int
raw = append(raw, '[')
res.ForEach(func(_, value gjson.Result) bool {
if i >= start {
if j > 0 {
raw = append(raw, ',')
}
raw = append(raw, value.Raw...)
j++
}
i++
return i < end
})
raw = append(raw, ']')
return gjson.ParseBytes(raw)
}
func main() {
json := `{"path":{"to":{"array":[0,1,2,3,4,5,6,7,8,9]}}}`
res := gjson.Get(json, "path.to.array")
println(sliceJSONArray(res, 0, 4).Raw)
println(sliceJSONArray(res, 3, 8).Raw)
}
// [0,1,2,3]
// [3,4,5,6,7]
Though it would be rad if there was a built in @slice
modifier, like path.to.array.@slice:[0,4]
It's possible to add a custom one, if you desire.
package main
import (
"math"
"github.com/tidwall/gjson"
)
func sliceJSONArray(json string, arg string) string {
res := gjson.Parse(json)
if !res.IsArray() {
return ""
}
start := int(gjson.Get(arg, "0").Int())
end := math.MaxInt
if jend := gjson.Get(arg, "1"); jend.Exists() {
end = int(jend.Int())
}
var raw []byte
var i, j int
raw = append(raw, '[')
res.ForEach(func(_, value gjson.Result) bool {
if i >= start {
if j > 0 {
raw = append(raw, ',')
}
raw = append(raw, value.Raw...)
j++
}
i++
return i < end
})
raw = append(raw, ']')
return string(raw)
}
func main() {
gjson.AddModifier("slice", sliceJSONArray)
json := `{"path":{"to":{"array":[0,1,2,3,4,5,6,7,8,9]}}}`
println(gjson.Get(json, "path.to.array.@slice:[0,4]").Raw)
println(gjson.Get(json, "path.to.array.@slice:[3,8]").Raw)
}
I think what we're trying to do is called "streamed json parsing". Did somebody perhaps do some benchmarks how doing partial parsing with gjson
compares to dedicated streaming json parsers e.g. json_stream or nop-json? Also would be really interesting having more docs & examples on this topic.
Hello, currently trying to figure out how to return a limited number of elements from an array as a single result, without just resorting to
path.to.array.[0,1,2,...,n]
.The most "elegant" way I've been able to figure out is:
Is there a simpler/more efficient way of doing this, maybe akin to
path.to.array.[0:n]
?