如何为Go结构体的一个属性适配两种JSON反序列化类型?
解决JSON字段多类型解析问题的Golang实现
核心思路
不用any类型,而是自定义Brand结构体并实现json.Unmarshaler接口,手动处理字符串ID和对象两种格式,实现兼容解析。
代码实现
首先定义Brand类型及产品结构体:
import "encoding/json" type Brand struct { Id string `json:"_id,omitempty"` Name string `json:"name,omitempty"` } type Product struct { Brand Brand `json:"brand,omitempty"` // 其他产品字段... }
给Brand实现json.Unmarshaler接口,处理两种解析场景:
func (b *Brand) UnmarshalJSON(data []byte) error { // 先尝试解析为字符串ID格式 var id string if err := json.Unmarshal(data, &id); err == nil { b.Id = id b.Name = "" // 字符串格式无名称字段,置空 return nil } // 字符串解析失败,尝试解析为对象格式 type brandAlias Brand // 用别名避免递归调用自身UnmarshalJSON var alias brandAlias if err := json.Unmarshal(data, &alias); err != nil { return err } *b = Brand(alias) return nil }
测试示例
场景1:Brand为对象格式
productObjJSON := `{ "brand": { "_id": "5f4ce4c7f78655de5807csa1", "name": "Apple" } }` var p1 Product if err := json.Unmarshal([]byte(productObjJSON), &p1); err != nil { panic(err) } // 输出:Brand{Id:"5f4ce4c7f78655de5807csa1", Name:"Apple"}
场景2:Brand为字符串ID格式
productStrJSON := `{ "brand": "5f4ce4c7f78655de5807csa1" }` var p2 Product if err := json.Unmarshal([]byte(productStrJSON), &p2); err != nil { panic(err) } // 输出:Brand{Id:"5f4ce4c7f78655de5807csa1", Name:""}
优势说明
- 全程避免
any类型,保证类型安全,后续代码无需做类型断言 - 逻辑清晰,明确处理两种格式,可扩展性强(若新增格式,直接在UnmarshalJSON中添加分支即可)
- 符合Golang JSON解析规范,代码维护性高
内容的提问来源于stack exchange,提问作者Emre SERBEST
相关产品推荐
相关产品推荐

