91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

golang?jsoniter?extension怎么處理動態字段

發布時間:2023-04-07 17:56:07 來源:億速云 閱讀:108 作者:iii 欄目:開發技術

這篇文章主要講解了“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 作為一個樣例

  • 包裝類,然后重新實現 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

感謝各位的閱讀,以上就是“golang jsoniter extension怎么處理動態字段”的內容了,經過本文的學習后,相信大家對golang jsoniter extension怎么處理動態字段這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长岭县| 海城市| 津南区| 察隅县| 灵山县| 巴东县| 吉水县| 搜索| 宁远县| 广河县| 泗阳县| 新乡县| 西安市| 定西市| 张掖市| 湖南省| 康乐县| 都匀市| 罗田县| 道孚县| 阳西县| 尼木县| 连云港市| 星座| 福泉市| 桦南县| 民丰县| 花垣县| 祁东县| 元氏县| 城口县| 依兰县| 雷山县| 青冈县| 商南县| 郑州市| 龙川县| 大港区| 乐陵市| 楚雄市| 措勤县|