【发布时间】:2016-04-26 20:02:57
【问题描述】:
package main
import (
"fmt"
"encoding/json"
"reflect"
)
type GeneralConfig map[string]interface{}
var data string = `
{
"key":"value",
"important_key":
{"foo":"bar"}
}`
func main() {
jsonData := &GeneralConfig{}
json.Unmarshal([]byte(data), jsonData)
fmt.Println(reflect.TypeOf(jsonData)) //main.GeneralConfig
jsonTemp := (*jsonData)["important_key"]
fmt.Println(reflect.TypeOf(jsonTemp)) //map[string]interface {}
//newGeneralConfig := GeneralConfig(jsonTemp)
//cannot convert jsonTemp (type interface {}) to type GeneralConfig:
//need type assertion
newGeneralConfig := jsonTemp.(GeneralConfig)
//fmt.Println(reflect.TypeOf(newGeneralConfig))
//panic: interface conversion: interface {} is map[string]interface {},
//not main.GeneralConfig
}
可通过the playground获得
我知道我可以使用嵌套结构代替GeneralConfig,但这需要我知道有效负载的确切结构,即它不适用于不同的键(我会被锁定到“important_key” )。
当我不知道“important_key”的值是什么时,是否有 golang 解决方法?我说 golang,因为如果可能的话,可以要求所有“important_keys”都有一个恒定的父键,这可以解决这个问题。
总而言之,给定一个任意 json 对象,一定有一种方法可以遍历它的键,如果值是自定义类型,则将值转换为该类型。现在看来,如果我使用类型转换,它告诉我类型是interface{},我需要使用类型断言;但是,如果我使用类型断言,它会告诉我 interface{} 是 map[string]interface{} 而不是 main.GeneralConfig。
【问题讨论】:
-
我的建议是弄清楚架构。没有“任意”的 json 这样的东西,我真的厌倦了人们采取低劣的方法,因为他们认为他们的 json 是如此不可预测。我有消息要告诉你,不是!我已经用模式解析了更多变体和复杂的 json,这并不难。 json 是一种形式语言,有一个精确的模式来描述任何 blob,它们可以非常灵活。
-
当你有一个嵌套的 json 结构并解组它时,你最终会得到一个 map[string]interface{}。 interface{} 部分(如果它是嵌套部分)又是一个 map[string]interface{}。因此,您可以继续向下遍历,直到发现您的 interface{} 不是地图。如果您提供您想要使用的 json 示例,我们可以提出解决方案。
-
@evanmcdonnal 这更像是“理论上,我该怎么做?”出于实际目的,我得出了与您相同的结论。
-
这很酷。我还处理过类似的困惑,尝试从实际上表示接口切片或映射的接口解包数据。我只是觉得有必要给我的 2 美分,因为正如我所说,我最近在 SO 上看到了很多这样的问题,而且大多数时候作者实际上是在处理非常简单的 json,他们只是在用自己的脚射击这种假设没有一个简单的简明模式来描述它。
标签: go