0

I am new to go and I understand how to marshall json data into custom predefined Struct types but I'm currently working with a JSON set that can have dynamic keys & values with every call. I can marshall this dynamic data into a map/interface no problem but I'm a little lost with how to access the item that are deeply nested in an array.

Here is sample JSON that I'm working with from the USDOL website

    {
    "name": "osha-establishment",
    "count": 15,
    "frequency": "Manual Crawl",
    "version": 4,
    "newdata": true,
    "lastrunstatus": "success",
    "lastsuccess": "Mon Dec 08 2014 11:19:57 GMT+0000 (UTC)",
    "thisversionstatus": "success",
    "results": {
                    "est_search": [
                                    {
                                    "est_name": "Chipotle Mexican Grill",
                                    "state": "MN",
                                    "activity": {
                                        "href": "https://www.osha.gov/pls/imis/establishment.inspection_detail?id=317911832",
                                        "text": "317911832"
                                    },
                                    "opened": "11/20/2014",
                                    "rid": "0552700",
                                    "type": "Complaint",
                                    "sc": "Partial",
                                    "sic": {
                                        "href": "https://www.osha.gov/pls/imis/sic_manual.display?id=44&tab=description",
                                        "text": "5812"
                                    },
                                    "naics": "722110",
                                    "vio": ""
                                    },
                                    {
                                    "est_name": "Chipotle Mexican Grill, Inc.",
                                    "state": "AZ",
                                    "activity": {
                                        "href": "https://www.osha.gov/pls/imis/establishment.inspection_detail?id=317801066",
                                        "text": "317801066"
                                    },
                                    "opened": "07/14/2014",
                                    "rid": "0950411",
                                    "type": "Complaint",
                                    "sc": "Partial",
                                    "sic": {
                                        "href": "https://www.osha.gov/pls/imis/sic_manual.display?id=44&tab=description",
                                        "text": "5812"
                                    },
                                    "naics": "722211",
                                    "vio": "2"
                                    }
                                ]
                }
    }

I'd like to access the values of the sic keys in this JSON set.

Here is my broke go code:

package main

    import (
        "encoding/json"
        "log"
        "net/http"
    )

    func main() {
        resp, err := http.Get("https://www.kimonolabs.com/api/2oowt0xq?apikey=")

        if err != nil {
            // handle error
        }
        defer resp.Body.Close()

        var result map[string]interface{}

        dec := json.NewDecoder(resp.Body)
        if err := dec.Decode(&result); err != nil {
            // handle error
            log.Println("This is an error")
        }

        log.Println(result["results"].(map[string]interface{})["est_search"], err)

    }

Any help showing me how to access the sic values would be greatly appreciated.

1 Answer 1

1

To decode JSON into an interface value, Decode stores one of these in the interface value:

1. bool, for JSON booleans
2. float64, for JSON numbers
3. string, for JSON strings
4. []interface{}, for JSON arrays
5. map[string]interface{}, for JSON objects
6. nil for JSON null

According to rules above,

  • result["results"].(map[string]interface{})["est_search"] is []interface{} from JSON array (rule 4).
  • iterate over result["results"].(map[string]interface{})["est_search"].([]interface{}), each item is map[string]interface{} from JSON object (rule 5).

Here is the example code, I ran it and it seems to work with that URL;

package main

import (
    "fmt"
    "encoding/json"
    "net/http"
)

func main() {
    resp, err := http.Get("https://www.kimonolabs.com/api/2oowt0xq?apikey=DTgSLPbfOPauuLCXTws5jquLQd0V7kBB")

    if err != nil {
        // handle error
    }   
    defer resp.Body.Close()

    var result map[string]interface{}

    dec := json.NewDecoder(resp.Body)
    if err := dec.Decode(&result); err != nil {
        // handle error
        fmt.Println("This is an error")
    }   

    for _, item := range result["results"].(map[string]interface{})["est_search"].([]interface{}) {
        fmt.Println(item.(map[string]interface{})["sic"])
    }   
}
Sign up to request clarification or add additional context in comments.

1 Comment

This makes sense to me now. I knew that I had to iterate but I didn't realize I had to cast the array into interface. This explanation cleared this up for me.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.