Go语言中如何动态修改结构体字段的JSON键适配不同API请求?
动态调整结构体字段的JSON键以适配不同请求类型
你可以通过为结构体实现自定义的MarshalJSON和UnmarshalJSON方法来解决这个问题,无需额外定义重复结构体或冗余字段,也能避免直接使用反射带来的复杂度。
实现方案
首先定义基础结构体,将Vat字段的默认JSON标签设为"-",避免标准库自动处理它:
type SilverfinCompany struct { ID int `json:"id"` Name string `json:"name"` Vat string `json:"-"` // 禁用默认序列化/反序列化 }
处理GET请求的反序列化(解析vat字段)
实现UnmarshalJSON方法,内部用临时结构体匹配GET响应的JSON结构,再把值映射到原结构体:
func (c *SilverfinCompany) UnmarshalJSON(data []byte) error { type tempCompany struct { ID int `json:"id"` Name string `json:"name"` Vat string `json:"vat"` } var temp tempCompany if err := json.Unmarshal(data, &temp); err != nil { return err } c.ID = temp.ID c.Name = temp.Name c.Vat = temp.Vat return nil }
处理POST/PATCH请求的序列化(输出vat_identifier字段)
实现MarshalJSON方法,用临时结构体匹配POST/PATCH所需的JSON结构,将原结构体的值填充进去后再序列化:
func (c SilverfinCompany) MarshalJSON() ([]byte, error) { type tempCompany struct { ID int `json:"id"` Name string `json:"name"` VatIdentifier string `json:"vat_identifier"` } temp := tempCompany{ ID: c.ID, Name: c.Name, VatIdentifier: c.Vat, } return json.Marshal(temp) }
使用方式
和标准JSON操作完全一致,无需额外转换:
- 解析GET响应:
var company SilverfinCompany err := json.Unmarshal(getResponseBytes, &company) - 生成POST/PATCH请求体:
requestBytes, err := json.Marshal(company)
为什么不推荐反射?
虽然理论上可以通过反射遍历结构体字段、手动映射键名,但这种方式代码晦涩,且反射操作存在一定性能损耗。自定义序列化/反序列化方法的可读性和可维护性更强,是Go社区处理此类场景的常规方案。
内容的提问来源于stack exchange,提问作者Anders Finn Jørgensen
相关产品推荐
相关产品推荐

