douchen3562 2015-03-04 16:39
浏览 113
已采纳

在Python中将任何JSON转换为标准字典的golang等效项是什么?

In Python you can do something like this:

r = requests.get("http://wikidata.org/w/api.php", params=params)
data = r.json()

And now data is a dict or hash table (also, I did not need to define beforehand the structure of the dict), and I can access values of keys by doing data["entities"], data["entities"]["Q12"], etc.

How would I do this in golang? So far I have this:

resp, err := http.Get("http://wikidata.org/w/api.php?"+v.Encode())
if err != nil {
    // handle error
}

defer resp.Body.Close()
decoder := json.NewDecoder(resp.Body)
var data interface{}
decodeErr := decoder.Decode(&data)
if decodeErr != nil {
    // handle error
}
fmt.Println(data["entities"], data["entities"]["Q"+id])

Which gives me the compile error: invalid operation: data["entities"] (index of type interface {})

So what type should var data be? And do I need to define a structure to the JSON beforehand or is it possible to handle any JSON file/stream without modifying the code?

  • 写回答

1条回答 默认 最新

  • dongzhuo1498 2015-03-04 16:46
    关注

    If you want a dictionary, use the Go type map[string]interface{} (which is a map with string keys and values of any type):

    var data map[string]interface{}
    

    And then you can refer to its elements like:

    data["entities"]
    

    See this example:

    s := `{"text":"I'm a text.","number":1234,"floats":[1.1,2.2,3.3],
        "innermap":{"foo":1,"bar":2}}`
    
    var data map[string]interface{}
    err := json.Unmarshal([]byte(s), &data)
    if err != nil {
        panic(err)
    }
    
    fmt.Println("text =", data["text"])
    fmt.Println("number =", data["number"])
    fmt.Println("floats =", data["floats"])
    fmt.Println("innermap =", data["innermap"])
    
    innermap, ok := data["innermap"].(map[string]interface{})
    if !ok {
        panic("inner map is not a map!")
    }
    fmt.Println("innermap.foo =", innermap["foo"])
    fmt.Println("innermap.bar =", innermap["bar"])
    
    fmt.Println("The whole map:", data)
    

    Output:

    text = I'm a text.
    number = 1234
    floats = [1.1 2.2 3.3]
    innermap = map[foo:1 bar:2]
    innermap.foo = 1
    innermap.bar = 2
    The whole map: map[text:I'm a text. number:1234 floats:[1.1 2.2 3.3]
        innermap:map[foo:1 bar:2]]
    

    Try it on the Go Playground.

    Notes:

    Basically if your map is multi-level (the map contains another map) like the "innermap" in the above example, when you access the inner map, you can use Type assertion to have it as another map:

    innermap, ok := data["innermap"].(map[string]interface{})
    // If ok, innermap is of type map[string]interface{}
    // and you can refer to its elements.
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。