Go如何无需定义包装结构体,将嵌套HTTP JSON响应转为目标结构体切片
实现方案
共有三种常用方案可以避免单独定义全局ProductRes包装结构体,按简洁度和适用场景区分如下:
方案1:使用匿名临时结构体(最常用,无额外改造)
无需单独声明全局的ProductRes类型,仅在解析时声明匿名结构体接收外层响应即可:
// 仅保留你原有的Product定义即可 type Product struct { Name string `json:"name"` Price float64 `json:"price"` } // 解析部分代码修改为 var res struct { Items []Product `json:"items"` } if err := json.Unmarshal(body, &res); err != nil { log.Fatalln(err) } products := res.Items // 直接得到所需的Product切片
该方案无需额外改造逻辑,也不用维护多余的全局类型,适合绝大多数单次解析的场景。
方案2:直接解析到map(代码最短,适合简单结构)
如果响应外层只有items一个有用字段,可直接用map接收,连临时结构体的标签都不用写:
var res map[string][]Product if err := json.Unmarshal(body, &res); err != nil { log.Fatalln(err) } products := res["items"]
方案3:自定义反序列化方法(完全隐藏包装逻辑,最贴合需求)
如果要完全实现「仅操作Product相关类型就能完成解析」的效果,可以给Product切片定义别名并实现json.Unmarshaler接口,后续解析时直接对切片操作即可:
type Product struct { Name string `json:"name"` Price float64 `json:"price"` } // 定义切片别名,实现反序列化接口 type ProductList []Product func (pl *ProductList) UnmarshalJSON(data []byte) error { var tmp struct { Items []Product `json:"items"` } if err := json.Unmarshal(data, &tmp); err != nil { return err } *pl = tmp.Items return nil } // 解析时直接操作ProductList即可 var products ProductList if err := json.Unmarshal(body, &products); err != nil { log.Fatalln(err) } // 后续使用时ProductList和[]Product完全兼容,可直接转换
不建议你提到的「提前修改响应Body」的方案,手动截取JSON字符串容易因为格式换行、字段顺序、转义字符等问题出错,稳定性远低于上述原生解析方案。
内容的提问来源于stack exchange,提问作者Blake Rivell
相关产品推荐
相关产品推荐

