Home > Enterprise >  Iterating over Json for random object
Iterating over Json for random object

Time:09-23

I'm having issues querying over this json

{
   "cars":{
      "dfhuidsfiusd":{
         "name":"Mercedes",
          details: {
             "plate_number":"sas2-hd-3",
             "year": 2009
         }

      },
      "uiwouiouss":{
         "name":"Jaguar",
          details: {
             "plate_number":"sas2-hd-3",
             "year": 2009
         },
      },
      "sdikdshkjsd":{
         "name":"Toyota",
          details: {
             "plate_number":"sas2-hd-3",
             "year": 2009
         }
      }
   }
}

To get elements in the details object i need to pass through these random values which could change.

I decided to go with this library https://github.com/tidwall/gjson code :

result := gjson.Get(json, `cars.#.details(year="2009")`)

println(result.String())

Since they all value year=2009 in common, I am expecting the following output:

dfhuidsfiusd
sdikdshkjsd
uiwouiouss

But it's just prints empty

Putting these random values in an array and iterating might work, but I want to assume these values are not known beforehand, thanks.

CodePudding user response:

I read the documentation a bit, hope this helps:

package main

import (
    "github.com/tidwall/gjson"
)

func main() {
    json := `{
    "cars":{
       "dfhuidsfiusd":{
          "name":"Mercedes",
           "details": {
              "plate_number":"sas2-hd-3",
              "year": 2010
          }

       },
       "uiwouiouss":{
          "name":"Jaguar",
           "details": {
              "plate_number":"sas2-hd-3",
              "year": 2010
          },
       },
       "sdikdshkjsd":{
          "name":"Toyota",
           "details": {
              "plate_number":"sas2-hd-3",
              "year": 2012
          }
       }
    }
 }`

    result := gjson.Get(json, `cars.@values.#(details.year=2010)#.name`)

    println(result.String())
}

CodePudding user response:

I think it is not possible to get items' names by just using # or *. You have to iterate over those items manually:

gjson.Get(json, "cars").ForEach(func(path, value gjson.Result) bool {
    value.ForEach(func(method, value gjson.Result) bool {
        y := value.Get("year")
        if y.Int() == 2009 {
            fmt.Println(path)
        }
        return true
    })
    return true
})

CodePudding user response:

You can use the standard encoding/json package instead of adding an external dependency.

Unmarshal the JSON to a Go type matching the structure of the JSON. A Go map corresponds to a JSON object with unknown field names. Iterate through the result.

var v struct {
    Cars map[string]struct {
        Name    string
        Details struct {
            Plate_Number string
            Year         int
        }
    }
}
if err := json.Unmarshal(data, &v); err != nil {
    log.Fatal(err)
}
for k, car := range v.Cars {
    fmt.Println(k, car.Name, car.Details.Plate_Number, car.Details.Year)
}

The output of this program is:

uiwouiouss Jaguar sas2-hd-3 2009
sdikdshkjsd Toyota sas2-hd-3 2009
dfhuidsfiusd Mercedes sas2-hd-3 2009

Run the code here.

Use this code to collect the object keys where the year is 2009:

var keys []string
for k, car := range v.Cars {
    if car.Details.Year == 2009 {
        keys = append(keys, k)
    }
}
  • Related