golang反序列化json,不存在的字段设置默认值
问题
业务里要调第三方接口,返回的json里有俩字段可能有,也可能没有。
没有的情况和为0值的情况对应不同的业务逻辑,在编写代码的时候发现没法在struct上指定字段默认值。
其实可以先给struct的实例设置默认值,再去json.Unmarshal,但是第三方接口返回的json是一个嵌套的数组结构,我压根不知道json里面的BehaviorData数组有多少元素,没法这么玩。
解决方案
- 给对应的struct重写UnmarshalJSON方法
type BehaviorData struct {
AverageReplyTime int `json:"avg_reply_time"`
ReplyPercentage float32 `json:"reply_percentage"`
}
func (b *BehaviorData) UnmarshalJSON(data []byte) error {
// 给目标struct取个别名 避免下面Unmarshal(data, defaultData)时循环调用本方法
type BehaviorDataAlia BehaviorData
// 在序列化之前就设置好默认值
defaultData := &BehaviorDataAlia{
AverageReplyTime: -1,
ReplyPercentage: -1,
}
// json串反序列化到这个defaultData里 如果有字段缺席 那么刚刚写的默认值就会留下
_ = json.Unmarshal(data, defaultData)
// 本质上就是在b这个实例调用自身的Unmarshal前后包装了一下 这里把包装之后的data覆盖到b上去
*b = BehaviorData(*defaultData)
return nil
}
类似问题
struct在marshal成json字符串的时候,希望有自定义值/默认值
- 利用反射,自己封装unmarshal方法,利用反射来读取struct字段中的tag
type test struct { Name string `json:"name"` Addr string `json:"addr" default:"localhost"` Port uint `json:"port" default:"8080"` } func MarshalJson(i interface{}) ([]byte, error) { typeof := reflect.TypeOf(i) valueof := reflect.ValueOf(i) // 遍历这个obj的所有字段 for i := 0; i < typeof.Elem().NumField(); i { // 针对那些为0值得 if valueof.Elem().Field(i).IsZero() { def := typeof.Elem().Field(i).Tag.Get("default") if def != "" { switch typeof.Elem().Field(i).Type.String() { case "int": result, _ := strconv.Atoi(def) valueof.Elem().Field(i).SetInt(int64(result)) case "uint": result, _ := strconv.ParseUint(def, 10, 64) valueof.Elem().Field(i).SetUint(result) case "string": valueof.Elem().Field(i).SetString(def) } } } } return json.Marshal(i) } func main() { t := &test{ Name: "test server", } data, err := MarshalJon(t) if err != nil { panic(err) } fmt.Println(string(data)) } 结果: {"name":"test server","addr":"localhost","port":8080}
- 重写该struct的MarshalJSON方法,利用匿名结构体重复字段覆盖的机制
还可以通过类似方法给序列化之后的json串添加额外的字段func (d Message) MarshalJSON() ([]byte, error) { type Alias Message return json.Marshal(struct { Alias CreateAt string `json:"createAt"` }{ Alias: Alias(d), CreateAt: d.CreateAt.Format("2006/01/02 15:04:05"), }) }
详见文章golang重载MarshalJSON实现自定义序列化type Book struct { Title string Author string } type FakeBook Book func (b Book) MarshalJSON() ([]byte,error) { return json.Marshal(struct { FakeBook Genre string }{ FakeBook: FakeBook(b),Genre: "Satire",}) } //对Book对象的序列化结果: { "Title": "Catch-22","Author": "Joseph Heller","Genre": "Satire" //可以发现确实多了一个Genre字段 }
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhhbakaj
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13