tidwall / gjson

Get JSON values quickly - JSON parser for Go
MIT License
14.1k stars 846 forks source link

Support "@unique" modifier #230

Open Altenrion opened 3 years ago

Altenrion commented 3 years ago

I understand that this modifier can be easily done by anyone, but suppose that it migth be needed not only by me and it would be clearer to use from lib.

I suggest to add modifier @unique , if it would be not so hard.

gjson.AddModifier("unique", func(_json, arg string) string {
        var arr []string
        _ = json.Unmarshal([]byte(_json), &arr)

        keys := make(map[string]bool)
        var list []string

        for _, entry := range arr {
            if _, value := keys[entry]; !value {
                keys[entry] = true
                list = append(list, entry)
            }
        }
        data, _ := json.Marshal(list)
        return string(data)
    })

I Understand that there might be a lot of different cases , not only flat slice of strings.

I needed to extract uniq user_ids and count them, so I would provide my case here as example:

json_bytes := []byte(`{
  "agreements": [
    {"a_id":"1111", "policies":[
        {"id":"1", "insured_id":"123"},
        {"id":"2", "insured_id":"222"},
        {"id":"3", "insured_id":"333"},
    ]},
    {"a_id":"2222", "policies":[
        {"id":"4", "insured_id":"444"},
        {"id":"5", "insured_id":"222"},
        {"id":"6", "insured_id":"666"},
    ]},
  ]
}`)

    gjson.AddModifier("unique", func(_json, arg string) string {
        var arr []string
        _ = json.Unmarshal([]byte(_json), &arr)

        keys := make(map[string]bool)
        var list []string

        for _, entry := range arr {
            if _, value := keys[entry]; !value {
                keys[entry] = true
                list = append(list, entry)
            }
        }
        data, _ := json.Marshal(list)
        return string(data)
    })

    value := gjson.Get(string(json_bytes), "agreements.#.policies.#.insured_id|@flatten|@unique.#")
    println("result:",value.String())
result: 5

can discuss here and i can prepare PR

hotrush commented 2 years ago

Unique is useful, but i don't think that you need to unmarshal json, you can parse it with gjson, will be faster

the1337beauty commented 3 weeks ago

How would you do a similar modifier but to return unique structs/children within an array?