最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang jsoniter extension 處理動(dòng)態(tài)字段的實(shí)現(xiàn)方法

 更新時(shí)間:2023年04月06日 15:11:35   作者:皿小草  
這篇文章主要介紹了golang jsoniter extension 處理動(dòng)態(tài)字段的實(shí)現(xiàn)方法,我們使用實(shí)例級(jí)別的 extension, 而非全局,可以針對(duì)不同業(yè)務(wù)邏輯有所區(qū)分,jsoniter 包提供了比較完善的定制能力,通過例子可以感受一下擴(kuò)展性,需要的朋友可以參考下

1. 背景

golang 原生 json 包,在處理 json 對(duì)象的字段的時(shí)候,是需要嚴(yán)格匹配類型的。但是,實(shí)際上,當(dāng)我們與一些老系統(tǒng)或者腳本語言的系統(tǒng)對(duì)接的時(shí)候,有時(shí)候需要對(duì)類型需要做一下兼容,假設(shè)我們有以下需求

目標(biāo)類型輸入解析后
intint, string123, “123”123
stringint, string123, “123”“123”
timeunix_seconds, RFC33391680676884, “2023-04-05T14:41:24Z”,“2023-04-05T14:41:24Z”

2. 可選項(xiàng)

我們以 time 作為一個(gè)樣例

  • 包裝類,然后重新實(shí)現(xiàn) Unmarshal 接口
type MyTime struct {
	t    time.Time
}

功能可以實(shí)現(xiàn),但是如果使用的地方很多的情況下,就可能要改動(dòng)多處,而且,這是全局級(jí)別的,可能會(huì)影響到很多包的行為

  • 使用 jsonter 的 extension 實(shí)現(xiàn)

jsoniter 的插件文檔參考
我們使用實(shí)例級(jí)別的 extension, 而非全局,可以針對(duì)不同業(yè)務(wù)邏輯有所區(qū)分

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)
}

// 這里統(tǒng)一改用 unix seconds 進(jìn)行輸出
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 數(shù)字解析
					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)
}

我們?cè)诶又?,?shí)現(xiàn)了:

  • 把 p1 使用了 unix 數(shù)字進(jìn)行序列化
  • 在反序列化 p2/p3/p4的時(shí)候,兼容了 字符串/數(shù)字/null

總結(jié)

jsoniter 包提供了比較完善的定制能力,通過例子可以感受一下擴(kuò)展性。后續(xù)大家可以根據(jù)業(yè)務(wù)需求發(fā)掘更多的能力

到此這篇關(guān)于golang jsoniter extension 處理動(dòng)態(tài)字段的文章就介紹到這了,更多相關(guān)go動(dòng)態(tài)字段內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang進(jìn)行xml文件解析的操作方法

    golang進(jìn)行xml文件解析的操作方法

    本文介紹了Go語言中解析XML文件的幾種方法:小文件解析、大文件流式解析和復(fù)雜結(jié)構(gòu)解析,對(duì)于小文件,使用標(biāo)準(zhǔn)庫中的encoding/xml包;對(duì)于大文件,采用流式解析以避免內(nèi)存溢出,對(duì)于復(fù)雜結(jié)構(gòu)的XML文件,推薦使用第三方庫github.com/beevik/etree
    2024-11-11
  • 淺談Golang內(nèi)存逃逸

    淺談Golang內(nèi)存逃逸

    本文主要介紹了Golang內(nèi)存逃逸,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • golang基于websocket通信tcp keepalive研究記錄

    golang基于websocket通信tcp keepalive研究記錄

    這篇文章主要為大家介紹了golang基于websocket通信tcp keepalive研究記錄,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go語言如何并發(fā)超時(shí)處理詳解

    Go語言如何并發(fā)超時(shí)處理詳解

    大家都知道golang并沒有在語言層次上提供超時(shí)操作,但可以通過一些小技巧實(shí)現(xiàn)超時(shí)。下面來一起看看吧,有需要的朋友們可以參考借鑒。
    2016-09-09
  • 詳解golang函數(shù)多返回值錯(cuò)誤處理與error類型

    詳解golang函數(shù)多返回值錯(cuò)誤處理與error類型

    這篇文章主要為大家詳細(xì)介紹了golang中函數(shù)多返回值錯(cuò)誤處理與error類型的相關(guān)知識(shí),文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)吧
    2023-10-10
  • Go語言實(shí)現(xiàn)枚舉的示例代碼

    Go語言實(shí)現(xiàn)枚舉的示例代碼

    本文主要介紹了Go語言實(shí)現(xiàn)枚舉的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • golang 連接mongoDB的方法示例

    golang 連接mongoDB的方法示例

    這篇文章主要介紹了golang 連接mongoDB的方法示例,詳細(xì)的介紹了golang的基礎(chǔ)知識(shí)和連接mongoDB的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • 詳解go中panic源碼解讀

    詳解go中panic源碼解讀

    這篇文章主要介紹了go中panic源碼解讀,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • go實(shí)現(xiàn)一個(gè)內(nèi)存緩存系統(tǒng)的示例代碼

    go實(shí)現(xiàn)一個(gè)內(nèi)存緩存系統(tǒng)的示例代碼

    本文主要介紹了go實(shí)現(xiàn)一個(gè)內(nèi)存緩存系統(tǒng)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • Go設(shè)計(jì)模式之觀察者模式講解和代碼示例

    Go設(shè)計(jì)模式之觀察者模式講解和代碼示例

    觀察者是一種行為設(shè)計(jì)模式, 允許一個(gè)對(duì)象將其狀態(tài)的改變通知其他對(duì)象,觀察者模式提供了一種作用于任何實(shí)現(xiàn)了訂閱者接口的對(duì)象的機(jī)制, 可對(duì)其事件進(jìn)行訂閱和取消訂閱,本文就通過代碼示例給大家詳細(xì)介紹一下Go的觀察者模式,需要的朋友可以參考下
    2023-07-07

最新評(píng)論

尼勒克县| 高阳县| 雷波县| 澎湖县| 稷山县| 封丘县| 南雄市| 昌都县| 张家港市| 高邑县| 高要市| 禄丰县| 涿鹿县| 万安县| 杭州市| 锦屏县| 盐津县| 杭锦后旗| 长寿区| 白朗县| 肇源县| 台南市| 陵川县| 永修县| 沙洋县| 浦江县| 卢龙县| 许昌县| 安西县| 卢氏县| 安康市| 道真| 禄丰县| 普洱| 六安市| 怀来县| 大厂| 板桥市| 林周县| 勐海县| 新竹市|