You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:55:18