Skip to content

Commit

Permalink
Added group modifier
Browse files Browse the repository at this point in the history
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"}]
  • Loading branch information
tidwall committed Feb 2, 2022
1 parent f47e17d commit e4fc67c
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
36 changes: 36 additions & 0 deletions gjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -2671,6 +2671,7 @@ var modifiers = map[string]func(json, arg string) string{
"values": modValues,
"tostr": modToStr,
"fromstr": modFromStr,
"group": modGroup,
}

// AddModifier binds a custom modifier command to the GJSON syntax.
Expand Down Expand Up @@ -2972,6 +2973,41 @@ func modToStr(str, arg string) string {
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
type stringHeader struct {
data unsafe.Pointer
Expand Down
36 changes: 36 additions & 0 deletions gjson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2467,3 +2467,39 @@ func TestToFromStr(t *testing.T) {
res := Get(json, "[email protected].#.eventVersion.@tostr").Raw
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"]`)
}

0 comments on commit e4fc67c

Please sign in to comment.