返回顶部
首页 > 资讯 > 后端开发 > GO >golangjsoniterextension处理动态字段的实现方法
  • 211
分享到

golangjsoniterextension处理动态字段的实现方法

gojson动态字段go动态字段gojsoniterextension 2023-05-14 17:05:39 211人浏览 薄情痞子
摘要

目录1. 背景2. 可选项总结1. 背景 golang 原生 JSON 包,在处理 json 对象的字段的时候,是需要严格匹配类型的。但是,实际上,当我们与一些老系统或者脚本语言的系

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 作为一个样例

  • 包装类,然后重新实现 Unmarshal 接口
type MyTime struct {
	t    time.Time
}

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

  • 使用 jsonter 的 extension 实现

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

package main

import (
	"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) bool
	decodeFunc  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) = newTime

				case 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 Person
	err = jsoniterAPI.Unmarshal([]byte(`{"birth": 1680254527}`), &p2)
	if err != nil {
		panic(err)
	}
	fmt.Println("p2", p2)

	var p3 Person
	err = jsoniterAPI.Unmarshal([]byte(`{"birth": "2023-03-21T07:20:04+00:00"}`), &p3)
	if err != nil {
		panic(err)
	}
	fmt.Println("p3", p3)

	var p4 Person
	err = jsoniterAPI.Unmarshal([]byte(`{"birth": null}`), &p4)
	if err != nil {
		panic(err)
	}
	fmt.Println("p4", p4)
}

我们在例子中,实现了:

  • 把 p1 使用了 unix 数字进行序列化
  • 在反序列化 p2/p3/p4的时候,兼容了 字符串/数字/null

总结

jsoniter 包提供了比较完善的定制能力,通过例子可以感受一下扩展性。后续大家可以根据业务需求发掘更多的能力

到此这篇关于golang jsoniter extension 处理动态字段的文章就介绍到这了,更多相关go动态字段内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: golangjsoniterextension处理动态字段的实现方法

本文链接: https://lsjlt.com/news/203303.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • golangjsoniterextension处理动态字段的实现方法
    目录1. 背景2. 可选项总结1. 背景 golang 原生 json 包,在处理 json 对象的字段的时候,是需要严格匹配类型的。但是,实际上,当我们与一些老系统或者脚本语言的系...
    99+
    2023-05-14
    go json动态字段 go 动态字段 go jsoniter extension
  • mysql之动态增添字段实现方式
    目录数据库mybatis逆向工程新建springboot项目遇到的问题总结数据库 --用户表 CREATE TABLE `users` ( `id` int(11) NOT N...
    99+
    2023-05-20
    mysql动态增添字段 mysql增添字段 mysql字段增添
  • golang jsoniter extension怎么处理动态字段
    这篇文章主要讲解了“golang jsoniter extension怎么处理动态字段”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang jsonite...
    99+
    2023-07-05
  • mysql动态增添字段怎么实现
    今天小编给大家分享的是mysql动态增添字段怎么实现,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。目录数据库mybatis逆向工程新建springboot项目遇到的问题总结数据库--...
    99+
    2023-07-06
  • java动态代理的实现方法
    这篇文章主要介绍“java动态代理的实现方法”,在日常操作中,相信很多人在java动态代理的实现方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java动态代理的实现方法”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-20
  • Vue动态组件实现异常处理方法
    动态组件有两种常用场景: 一是动态路由: // 动态路由 export const asyncRouterMap: Array<RouteRecordRaw> = [ ...
    99+
    2023-02-01
    Vue动态组件 Vue动态组件异常处理
  • mybatis动态字段查询的方法是什么
    MyBatis提供了动态字段查询的方法,可以根据不同的条件动态选择需要查询的字段。以下是MyBatis中实现动态字段查询的方法:1....
    99+
    2023-09-29
    mybatis
  • Java 中的静态字段和静态方法
    目录一、静态变量静态变量声明静态变量测试二、静态方法静态方法测试静态方法是如何工作的为什么 Java Main 方法是静态方法三、静态常量四、总结先看看下面这一串代码: public...
    99+
    2024-04-02
  • Mybatis-Plus实现公共字段自动赋值的方法
    目录1 mybatis-plus实现自动填充指定字段1.1 需要修改的字段在模型类上添加1.2 新建一个MetaObjectHandler的实现类2 通用字段自动填充的最佳实践总结2...
    99+
    2024-04-02
  • 利用java实现动态代理的方法
    这篇文章将为大家详细讲解有关利用java实现动态代理的方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。java 动态代理的方法总结AOP的拦截功能是由java中的动态代理来实现的。说白了,...
    99+
    2023-05-31
    java 动态代理 ava
  • Vue动态生成数据字段的实例
    目录动态生成数据字段实例1.父组件定义data里面的数据字段2.子组件接收数据3.因为获取数据是异步操作4.计算属性计算两个变量是否均完成5.子组件完整代码表单动态生成字段 ...
    99+
    2024-04-02
  • go结构体动态添加字段的方法是什么
    在Go语言中,结构体是一种固定字段的数据类型,无法动态添加字段。这是因为Go语言是静态类型语言,所有的变量和字段必须在编译时确定。如...
    99+
    2023-10-10
    go
  • SpringBoot2动态@Value的实现方法
    这篇文章主要介绍“SpringBoot2动态@Value的实现方法”,在日常操作中,相信很多人在SpringBoot2动态@Value的实现方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoo...
    99+
    2023-06-20
  • Java实现动态代理的方法有哪些
    这篇文章将为大家详细讲解有关Java实现动态代理的方法有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。详解Java动态代理的实现及应用Java动态代理其实写日常业务代码是不常用的,但在框...
    99+
    2023-05-31
    java 动态代理 ava
  • shell脚本实现字符串的动态替换方法
    目录背景代码使用示例用shell实现某行字符串的替换背景 我们有时候需要完成字符串的多组替换,比如需要完成以下替换 将“小草”替换为“真是让人印象深刻”将“小狗...
    99+
    2024-04-02
  • mybatis plus更新字段为null处理方法
    目录测试代码如下数据库表实体类mappercontroller运行测试运行测试mybatis plus 将字段更新为 null,默认如果不做任何处理,使用 mybatis plus ...
    99+
    2024-04-02
  • java实现动态编译并动态加载的方法
    小编给大家分享一下java实现动态编译并动态加载的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在D盘test目录下有个java文件:AlTest.javap...
    99+
    2023-06-14
  • dedecms5.7sp1评论添加字段的实现方法
    dedecms5.7sp1评论添加字段的解决方法问题,问题得以解决: 实现方法如下: 1,后台:系统—SQL命令运行器 中输入: alter table dede_feedback add column we...
    99+
    2022-06-12
    评论 添加字段
  • Java中的静态字段和静态方法怎么用
    这篇文章主要介绍了Java中的静态字段和静态方法怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。先看看下面这一串代码:public class Mai...
    99+
    2023-06-29
  • Java动态代理的原理及实现方法是什么
    本篇内容主要讲解“Java动态代理的原理及实现方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java动态代理的原理及实现方法是什么”吧!代理是指:某些场景下对象会找一个代理对象,来辅助...
    99+
    2023-07-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作