forked from mirror/gjson
Added group modifier
The new "@group" modifier allows for grouping arrays of objects. For example, using the "@group" modifier on the following json... {"id":["123","456","789"],"val":[2,1]} will results in... [{"id":"123","val":2},{"id":"456","val":1},{"id":"789"}]
This commit is contained in:
parent
f47e17d70a
commit
e4fc67c92a
36
gjson.go
36
gjson.go
|
@ -2671,6 +2671,7 @@ var modifiers = map[string]func(json, arg string) string{
|
||||||
"values": modValues,
|
"values": modValues,
|
||||||
"tostr": modToStr,
|
"tostr": modToStr,
|
||||||
"fromstr": modFromStr,
|
"fromstr": modFromStr,
|
||||||
|
"group": modGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddModifier binds a custom modifier command to the GJSON syntax.
|
// AddModifier binds a custom modifier command to the GJSON syntax.
|
||||||
|
@ -2972,6 +2973,41 @@ func modToStr(str, arg string) string {
|
||||||
return string(data)
|
return string(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func modGroup(json, arg string) string {
|
||||||
|
res := Parse(json)
|
||||||
|
if !res.IsObject() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var all [][]byte
|
||||||
|
res.ForEach(func(key, value Result) bool {
|
||||||
|
if !value.IsArray() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
var idx int
|
||||||
|
value.ForEach(func(_, value Result) bool {
|
||||||
|
if idx == len(all) {
|
||||||
|
all = append(all, []byte{})
|
||||||
|
}
|
||||||
|
all[idx] = append(all[idx], ("," + key.Raw + ":" + value.Raw)...)
|
||||||
|
idx++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
var data []byte
|
||||||
|
data = append(data, '[')
|
||||||
|
for i, item := range all {
|
||||||
|
if i > 0 {
|
||||||
|
data = append(data, ',')
|
||||||
|
}
|
||||||
|
data = append(data, '{')
|
||||||
|
data = append(data, item[1:]...)
|
||||||
|
data = append(data, '}')
|
||||||
|
}
|
||||||
|
data = append(data, ']')
|
||||||
|
return string(data)
|
||||||
|
}
|
||||||
|
|
||||||
// stringHeader instead of reflect.StringHeader
|
// stringHeader instead of reflect.StringHeader
|
||||||
type stringHeader struct {
|
type stringHeader struct {
|
||||||
data unsafe.Pointer
|
data unsafe.Pointer
|
||||||
|
|
|
@ -2467,3 +2467,39 @@ func TestToFromStr(t *testing.T) {
|
||||||
res := Get(json, "Message.@fromstr.Records.#.eventVersion.@tostr").Raw
|
res := Get(json, "Message.@fromstr.Records.#.eventVersion.@tostr").Raw
|
||||||
assert(t, res == `["\"2.1\""]`)
|
assert(t, res == `["\"2.1\""]`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGroup(t *testing.T) {
|
||||||
|
json := `{"id":["123","456","789"],"val":[2,1]}`
|
||||||
|
res := Get(json, "@group").Raw
|
||||||
|
assert(t, res == `[{"id":"123","val":2},{"id":"456","val":1},{"id":"789"}]`)
|
||||||
|
|
||||||
|
json = `
|
||||||
|
{
|
||||||
|
"issues": [
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"labels": [
|
||||||
|
"milestone_1",
|
||||||
|
"group:foo",
|
||||||
|
"plan:a",
|
||||||
|
"plan:b"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"id": "123"
|
||||||
|
},{
|
||||||
|
"fields": {
|
||||||
|
"labels": [
|
||||||
|
"milestone_1",
|
||||||
|
"group:foo",
|
||||||
|
"plan:a",
|
||||||
|
"plan"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"id": "456"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
res = Get(json, `{"id":issues.#.id,"plans":issues.#.fields.labels.#(%"plan:*")#|#.#}|@group|#(plans>=2)#.id`).Raw
|
||||||
|
assert(t, res == `["123"]`)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue