文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

golang jsoniter extension怎么处理动态字段

2023-07-05 22:29

关注

这篇文章主要讲解了“golang jsoniter extension怎么处理动态字段”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang jsoniter extension怎么处理动态字段”吧!

1. 背景

golang 原生 json 包,在处理 json 对象的字段的时候,是需要严格匹配类型的。但是,实际上,当我们与一些老系统或者脚本语言的系统对接的时候,有时候需要对类型需要做一下兼容,假设我们有以下需求


目标类型输入解析后
intint, string123, “123”123
stringint, string123, “123”“123”
timeunix_seconds, RFC33391680676884, “2023-04-05T14:41:24Z”,“2023-04-05T14:41:24Z”

2. 可选项

我们以 time 作为一个样例

type MyTime struct {t    time.Time}

功能可以实现,但是如果使用的地方很多的情况下,就可能要改动多处,而且,这是全局级别的,可能会影响到很多包的行为

jsoniter 的插件文档参考
我们使用实例级别的 extension, 而非全局,可以针对不同业务逻辑有所区分

package mainimport ("fmt""reflect""strconv""time""unsafe"jsoniter "github.com/json-iterator/go""github.com/modern-go/reflect2")type sampleExtension struct {jsoniter.DummyExtension}type wrapEncoder struct {encodeFunc  func(ptr unsafe.Pointer, stream *jsoniter.Stream)isEmptyFunc func(ptr unsafe.Pointer) booldecodeFunc  func(ptr unsafe.Pointer, iter *jsoniter.Iterator)}func (enc *wrapEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {enc.encodeFunc(ptr, stream)}func (codec *wrapEncoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {codec.decodeFunc(ptr, iter)}func (enc *wrapEncoder) IsEmpty(ptr unsafe.Pointer) bool {if enc.isEmptyFunc == nil {return false}return enc.isEmptyFunc(ptr)}// 这里统一改用 unix seconds 进行输出func (e *sampleExtension) CreateEncoder(typ reflect2.Type) jsoniter.ValEncoder {if typ.Kind() == reflect.Struct && typ.Type1().PkgPath() == "time" && typ.String() == "time.Time" {return &wrapEncoder{func(ptr unsafe.Pointer, stream *jsoniter.Stream) {t := *(*time.Time)(ptr)data := strconv.Itoa(int(t.Unix()))stream.WriteRaw(data)},nil,nil,}}return nil}func (e *sampleExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {if typ.Kind() == reflect.Struct && typ.Type1().PkgPath() == "time" && typ.String() == "time.Time" {return &wrapEncoder{decodeFunc: func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {switch iter.WhatIsNext() {case jsoniter.NumberValue: // 兼容 unix 数字解析timeUnix := iter.ReadInt()newTime := time.Unix(int64(timeUnix), 0)*(*time.Time)(ptr) = newTimecase jsoniter.NilValue:iter.Skip()case jsoniter.StringValue:timeStr := iter.ReadString()newTime, err := time.Parse(time.RFC3339, timeStr)if err != nil {fmt.Println("Unmarshal err", err)}*(*time.Time)(ptr) = newTime}},}}return nil}type Person struct {Birth time.Time `json:"birth"`}func main() {extension := &sampleExtension{}jsoniterAPI := jsoniter.Config{}.Froze()jsoniterAPI.RegisterExtension(extension)var p1 = Person{Birth: time.Now(),}j, err := jsoniterAPI.MarshalToString(p1)if err != nil {panic(err)}fmt.Println(j)var p2 Personerr = jsoniterAPI.Unmarshal([]byte(`{"birth": 1680254527}`), &p2)if err != nil {panic(err)}fmt.Println("p2", p2)var p3 Personerr = jsoniterAPI.Unmarshal([]byte(`{"birth": "2023-03-21T07:20:04+00:00"}`), &p3)if err != nil {panic(err)}fmt.Println("p3", p3)var p4 Personerr = jsoniterAPI.Unmarshal([]byte(`{"birth": null}`), &p4)if err != nil {panic(err)}fmt.Println("p4", p4)}

我们在例子中,实现了:

感谢各位的阅读,以上就是“golang jsoniter extension怎么处理动态字段”的内容了,经过本文的学习后,相信大家对golang jsoniter extension怎么处理动态字段这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯