如何从Go map对象中访问深度嵌套的JSON对象?

huangapple go评论83阅读模式
英文:

How do I access deeply embedded json objects from a go map object?

问题

我是新手,我知道如何将JSON数据编组到预定义的自定义结构类型中,但我目前正在处理一个每次调用都可能具有动态键和值的JSON集合。我可以将这个动态数据编组成一个map/interface,没有问题,但是我对如何访问嵌套在数组中的项目有点困惑。

这是我正在使用的来自USDOL网站的示例JSON:

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

我想访问这个JSON集合中sic键的值。

这是我错误的Go代码:

package main

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

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

if err != nil {
	// 处理错误
}
defer resp.Body.Close()

var result map[string]interface{}

dec := json.NewDecoder(resp.Body)
if err := dec.Decode(&result); err != nil {
	// 处理错误
	log.Println("这是一个错误")
}

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

}

帮助我如何访问sic值的任何帮助将不胜感激。

英文:

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

得分: 1

将JSON解码为接口值时,Decode将以下内容之一存储在接口值中:

  1. bool,用于JSON布尔值
  2. float64,用于JSON数字
  3. string,用于JSON字符串
  4. []interface{},用于JSON数组
  5. map[string]interface{},用于JSON对象
  6. nil,用于JSON null

根据上述规则,

  • result["results"].(map[string]interface{})["est_search"] 是来自JSON数组的 []interface{}(规则4)。
  • 遍历 result["results"].(map[string]interface{})["est_search"].([]interface{}),每个项都是来自JSON对象的 map[string]interface{}(规则5)。

以下是示例代码,我运行了它,似乎可以使用该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 {
        // 处理错误
    }   
    defer resp.Body.Close()

    var result map[string]interface{}

    dec := json.NewDecoder(resp.Body)
    if err := dec.Decode(&result); err != nil {
        // 处理错误
        fmt.Println("这是一个错误")
    }   

    for _, item := range result["results"].(map[string]interface{})["est_search"].([]interface{}) {
        fmt.Println(item.(map[string]interface{})["sic"])
    }   
}
英文:

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

huangapple
  • 本文由 发表于 2014年12月22日 09:41:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/27595599.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定