从Web服务器处理JSON响应时会有一些不便。
例如,我不知道JSON的数据结构(并且不想建模),只想从中获取值!
所以,对于Python,我可以写
value = response["body"][4]["data"]["uid"] //response is a dictionary
但对于Golang,我需要对每个元素进行断言!
value := response["body"].([]interface{})[4].(map[string]interface{})["data"].(map[string]interface{})["uid"]
//response is a map[string]interface{}
这是我在golang中写的,以获得我需要的值。你有什么建议吗?这种情况有什么有用的提示吗?
答案 0 :(得分:4)
如果使用结构对JSON对象建模并将其解组为该值,那么您不需要那些丑陋的索引并键入断言,您可以简单地引用结构字段。
请注意,您不必担心响应复杂,您只需要对要使用的部件进行建模。例如。如果响应是具有一百个字段但只需要2的对象,则创建仅包含这两个字段的结构。
如果您不想为JSON对象建模(或者因为它是动态的而不能建模),那么您可以编写一个通用实用程序函数,该函数根据路径获取值(系列地图键和切片索引),您可以在此答案中看到:Taking a JSON string, unmarshaling it into a map[string]interface{}, editing, and marshaling it into a []byte seems more complicated then it should be
最后,您可以使用已包含此帮助程序功能的第三方库,例如https://github.com/icza/dyno(披露:我是作者)。
使用github.com/icza/dyno
,它看起来像这样:
value, err := dyno.Get(response, "body", 4, "data", "uid")
答案 1 :(得分:0)
根据icza,您可以为JSON对象创建结构。但是如果你得到JSON结构,你从一开始就不知道。然后,您可以使用对接口的反射创建动态解析,这将是一个解析JSON数据的递归函数。
func main(){
var data interface{}
err := json.Unmarshal([]bytes(file.json), &data)
if err != nil {
panic(err)
}
var itemData map[string]interface{}
itemsMap := data.(map[string]interface{})
jsonParsedObject := interate(itemsMap)
log.Println(jsonParsedObject)
}
func iterate(data interface{}) interface{} {
if reflect.ValueOf(data).Kind() == reflect.Slice {
d := reflect.ValueOf(data)
tmpData := make([]interface{}, d.Len())
returnSlice := make([]interface{}, d.Len())
for i := 0; i < d.Len(); i++ {
tmpData[i] = d.Index(i).Interface()
}
for i, v := range tmpData {
returnSlice[i] = iterate(v)
}
return returnSlice
} else if reflect.ValueOf(data).Kind() == reflect.Map {
d := reflect.ValueOf(data)
tmpData := make(map[string]interface{})
for _, k := range d.MapKeys() {
typeOfValue := reflect.TypeOf(d.MapIndex(k).Interface()).Kind()
if typeOfValue == reflect.Map || typeOfValue == reflect.Slice {
tmpData[k.String()] = iterate(d.MapIndex(k).Interface())
} else {
tmpData[k.String()] = d.MapIndex(k).Interface()
}
}
return tmpData
}
return data
}