如何在Go中将含未知字段名的JSON反序列化为结构体?
如何反序列化含有未知字段但内部结构固定的JSON?
当然可以搞定!这种场景在处理第三方API返回时太常见了——外层字段名不确定,但里面的结构完全一致。用Go的map[string]自定义结构体就能轻松解决这个问题,我给你完善一下你的代码,直接看示例就懂了:
首先,我们需要把内部固定结构的部分定义成一个结构体,对应JSON里的known_field_1、known_field_2、known_field_3:
type mData struct { KnownField1 [][]int `json:"known_field_1"` KnownField2 [][]int `json:"known_field_2"` KnownField3 [][]int `json:"known_field_3"` }
然后,因为根节点是一个未知名称的键对应这个mData结构,我们直接把整个JSON反序列化为map[string]mData就行,不需要额外的包装结构体(当然你要加也可以,但没必要)。完整代码如下:
package main import "fmt" import "encoding/json" var body = []byte(`{ "unknown_field": { "known_field_1": [[1,2,3,4,5],[10,20,30,40,50],[100,200,300,400,500]], "known_field_2": [[11,21,31,41,51]], "known_field_3": [[12,22,32,42,52],[14,44,34,44,54]] } }`) type mData struct { KnownField1 [][]int `json:"known_field_1"` KnownField2 [][]int `json:"known_field_2"` KnownField3 [][]int `json:"known_field_3"` } func main() { var result map[string]mData err := json.Unmarshal(body, &result) if err != nil { fmt.Printf("反序列化出错:%v\n", err) return } // 遍历map就能拿到未知的字段名和对应的数据 for fieldName, data := range result { fmt.Printf("捕获到未知字段:%s\n", fieldName) fmt.Printf("known_field_1 数据:%v\n", data.KnownField1) fmt.Printf("known_field_2 数据:%v\n", data.KnownField2) fmt.Printf("known_field_3 数据:%v\n", data.KnownField3) } }
为什么这能行?
Go的encoding/json包会自动把JSON对象的键值对映射到map[string]T结构里——这里的T就是我们定义的mData,它会自动匹配JSON里对应的已知字段。不管根节点的键叫unknown_field还是下次返回变成random_field_123,都能被map捕获到,遍历一下就能拿到字段名和所有内部数据。
额外小提示
如果JSON里的内部字段可能存在缺失的情况,你可以把结构体字段改成指针类型,这样就能判断某个字段是否存在了:
type mData struct { KnownField1 *[][]int `json:"known_field_1"` KnownField2 *[][]int `json:"known_field_2"` KnownField3 *[][]int `json:"known_field_3"` }
这样如果JSON里没有known_field_2,对应的指针就是nil,你可以通过if data.KnownField2 != nil来判断。
内容的提问来源于stack exchange,提问作者Игорь
相关产品推荐
相关产品推荐

