gjson icon indicating copy to clipboard operation
gjson copied to clipboard

Is there a way to sort an array of objects by an object.property?

Open marang opened this issue 5 years ago • 1 comments

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 } ] }

marang avatar Nov 11 '20 15:11 marang

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
    }
  ]
}

tidwall avatar Dec 01 '20 20:12 tidwall