gjson
gjson copied to clipboard
Is there a way to sort an array of objects by an object.property?
Is there a way to sort an array of objects by an object.property?
i'd like to sort the farvourites array by favourites.sortingOrder descending
{ "favourites": [{ "name": "abc", "sortingOrder": 107 }, { "name": "bcd", "sortingOrder": 283 } ] }
There's nothing built into the gjson path syntax for sorting.
You'll need to somehow extract the elements as an array of gjson.Result, use the Result.Less function to compare, and the recreate the array.
Another option is to extend gjson by add a custom modifier function that performs those operations automatically.
Here's an example that I whipped up:
package main
import (
"sort"
"strings"
"github.com/tidwall/gjson"
)
func main() {
gjson.AddModifier("sort", func(json, arg string) string {
r := gjson.Get(json, gjson.Get(arg, "array").String())
if !r.IsArray() || r.Index == 0 {
return json
}
orderBy := gjson.Get(arg, "orderBy").String()
caseSensitive := gjson.Get(arg, "caseSensitive").Bool()
desc := gjson.Get(arg, "desc").Bool()
arr := r.Array()
sort.SliceStable(arr, func(i, j int) bool {
a := arr[i].Get(orderBy)
b := arr[j].Get(orderBy)
if desc {
return b.Less(a, caseSensitive)
}
return a.Less(b, caseSensitive)
})
var sorted strings.Builder
sorted.WriteByte('[')
for i, item := range arr {
if i > 0 {
sorted.WriteByte(',')
}
sorted.WriteString(item.Raw)
}
sorted.WriteByte(']')
return json[:r.Index] + sorted.String() + json[r.Index+len(r.Raw):]
})
json := `{ "favourites": [
{ "name": "abc", "sortingOrder": 999 },
{ "name": "bcd", "sortingOrder": 283 }
]}`
json = gjson.Get(json, `@sort:{"array":"favourites","orderBy":"sortingOrder","desc":true}.@pretty`).Raw
println(json)
}
output:
{
"favourites": [
{
"name": "abc",
"sortingOrder": 999
},
{
"name": "bcd",
"sortingOrder": 283
}
]
}