我正在将JSON从API解析为结构。我代表该结构的代码无法正常工作,我注意到这是因为API返回的是可变深度数组(例如,有时[] float64,有时[] [] float64)。我不知道如何设计一个结构来处理这个问题。
我已经尝试通过在[] float64,[] [] float64和[] interface {}之间交换有问题的类型来弄乱我的结构定义。
我的结构定义代码:
...
Geometries []struct {
Type string `json:"type"`
Coordinates []float64 `json:"coordinates"`
} `json:"geometries"`
...
以下是API的示例输出:
...
"geometries": [{"type": "Point", "coordinates": [-81.7046006, 41.4955689]}, {"type": "Polygon", "coordinates": [[[-81.7176885, 41.507513], [-81.7205424, 41.4857622], [-81.6915158, 41.4836231], [-81.6886557, 41.5053737], [-81.7176885, 41.507513]]]}]
...
我希望JSON能够解析到该结构中。相反,我在代码中看到以下错误:
json: cannot unmarshal array into Go struct field .coordinates of type float64
答案 0 :(得分:2)
使用json.RawMessage捕获随几何类型而变化的值:
Geometries []struct {
Type string `json:"type"`
Coordinates json.RawMessage `json:"coordinates"`
} `json:"geometries"`
将坐标解组为适合每种类型的值:
for _, geo := range x.Geometries {
switch geo.Type {
case "Point":
var coords []float64
if err := json.Unmarshal(geo.Coordinates, &coords); err != nil {
log.Fatal(err)
}
fmt.Println(coords)
case "Polygon":
var coords [][][]float64
if err := json.Unmarshal(geo.Coordinates, &coords); err != nil {
log.Fatal(err)
}
fmt.Println(coords)
}
}
另一种选择是解组到interface{}
并使用type assertions来挖掘值:
Geometries []struct {
Type string `json:"type"`
Coordinates interface{} `json:"coordinates"`
} `json:"geometries"`
...
for _, geo := range x.Geometries {
fmt.Println(geo.Type)
dump(geo.Coordinates, "")
}
...
func dump(v interface{}, indent string) {
switch v := v.(type) {
case []interface{}:
fmt.Println(indent, "[")
for _, v := range v {
dump(v, indent+" ")
}
fmt.Println(indent, "]")
default:
fmt.Println(indent, v)
}
}