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:
tidwall 2022-02-02 04:42:46 -07:00
parent f47e17d70a
commit e4fc67c92a
2 changed files with 72 additions and 0 deletions

View File

@ -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

View File

@ -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"]`)
}