JSON反序列化含未知键数据时得到空结构体的问题
解决Go中动态顶层键的JSON反序列化问题
你的问题其实出在两个关键地方,咱们一步步拆解解决:
核心问题分析
- 你给
Order里的Result字段加了json:"-"标签——这个标签的作用是让JSON反序列化时直接忽略该字段,不管JSON里有什么数据,这个字段都会是零值结构体。 - 顶层是动态变化的未知键,直接用嵌套结构体的方式,Go的JSON包没法把这个动态键和你的
Result字段对应起来。
解决方案一:用map[string]Result直接接收(最简单)
既然顶层是动态键,直接用map来承接是最直观的方式,map的键对应JSON里的未知动态键,值就是你定义好的Result结构体:
type Result struct { Sum float64 `json:"sum"` Low float64 `json:"low"` Avg float64 `json:"avg"` } // 用map接收动态键和对应数据 var resultMap map[string]Result err := json.Unmarshal([]byte(body), &resultMap) if err != nil { // 这里处理反序列化错误,比如log.Fatal(err) } // 遍历map获取结果(因为顶层键未知,需要遍历取出) for dynamicKey, result := range resultMap { fmt.Printf("动态键: %s, Sum: %.6f, Low: %.6f, Avg: %.6f\n", dynamicKey, result.Sum, result.Low, result.Avg) }
解决方案二:自定义UnmarshalJSON适配Order结构体
如果你想保留Order结构体的形式,可以给它实现自定义的反序列化方法,手动处理动态键的逻辑:
type Order struct { Result Result } type Result struct { Sum float64 `json:"sum"` Low float64 `json:"low"` Avg float64 `json:"avg"` } // 给Order实现自定义反序列化方法 func (o *Order) UnmarshalJSON(data []byte) error { // 先定义临时map承接动态键和Result数据 tempMap := make(map[string]Result) if err := json.Unmarshal(data, &tempMap); err != nil { return err } // 假设JSON顶层只有一个动态键(根据你的示例),取第一个值赋值给Order.Result for _, res := range tempMap { o.Result = res break } return nil } // 使用方式和你原来的代码一致 var order Order err := json.Unmarshal([]byte(body), &order) if err != nil { // 处理错误 } fmt.Printf("反序列化结果: %+v\n", order.Result)
再回头看你原来的问题
你原来的结构体里json:"-"标签是致命错误,它直接让JSON包跳过了Result字段;就算去掉这个标签,因为顶层键是未知的,JSON包也找不到和Result字段匹配的键,最终还是会得到零值结构体。
内容的提问来源于stack exchange,提问作者ntonnelier
相关产品推荐
相关产品推荐

