go icon indicating copy to clipboard operation
go copied to clipboard

多个不同库的 RegisterTypeDecoderFunc 会覆盖?

Open hiscaler opened this issue 3 years ago • 7 comments

我用了 A 库 和 B 库,两者都设置了 RegisterTypeDecoderFunc,比如

// A 库
jsoniter.RegisterTypeDecoderFunc("bool", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
		switch iter.WhatIsNext() {
		case jsoniter.StringValue:
			var t bool
			v := strings.TrimSpace(iter.ReadString())
			if v != "" {
				var err error
				if t, err = strconv.ParseBool(strings.ToLower(v)); err != nil {
					iter.Error = err
					return
				}
			}
			*((*bool)(ptr)) = t
		case jsoniter.NumberValue:
			if v, err := iter.ReadNumber().Int64(); err != nil {
				iter.Error = err
				return
			} else {
				*((*bool)(ptr)) = v > 0
			}
		case jsoniter.NilValue:
			iter.Skip()
			*((*bool)(ptr)) = false
		default:
			*((*bool)(ptr)) = iter.ReadBool()
		}
	})
// B 库
jsoniter.RegisterTypeDecoderFunc("bool", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
		switch iter.WhatIsNext() {
		case jsoniter.StringValue:
			var t bool
			v := strings.TrimSpace(iter.ReadString())
			if v != "" {
				var err error
				if t, err = strconv.ParseBool(strings.ToLower(v)); err != nil {
					iter.Error = err
					return
				}
			}
			*((*bool)(ptr)) = t
		case jsoniter.NumberValue:
			if v, err := iter.ReadNumber().Int64(); err != nil {
				iter.Error = err
				return
			} else {
				*((*bool)(ptr)) = v == 0
			}
		case jsoniter.NilValue:
			iter.Skip()
			*((*bool)(ptr)) = false
		default:
			*((*bool)(ptr)) = iter.ReadBool()
		}
	})

简单的说就是 A 库 1 看做是 True,而 B 库 0 看做是 True,如果同一个方法中同时使用了两个库,则会导致混乱。请问有什么办法避免吗?

hiscaler avatar Jul 12 '22 01:07 hiscaler

same problem

mjscjj avatar Sep 20 '22 07:09 mjscjj

请问你是怎么解决的?

mjscjj avatar Sep 20 '22 07:09 mjscjj

@mjscjj 没找到办法,所以没处理了

hiscaler avatar Sep 22 '22 01:09 hiscaler

相同的问题,json-iterator 怎么能new一个局部实例然后再RegisterTypeDecoderFunc使用呢,这样就不影响他人了

iyaozhen avatar Oct 17 '22 03:10 iyaozhen

@hiscaler @mjscjj 我解决了,使用 RegisterExtension 还有一个点就是需要重新定义一个config,这样只这个config生效

type customNumberExtension struct {
	jsoniter.DummyExtension
}

func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
	if typ.String() == "interface {}" {
		return &numberValDecoder{}
	}
	return nil
}

type numberValDecoder struct{}

func (n *numberValDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
	switch iter.WhatIsNext() {
	case jsoniter.NumberValue:
		var number any
		// 省略具体的业务逻辑
		*(*interface{})(ptr) = number
	default:
		*(*interface{})(ptr) = iter.Read()
	}
}

var newConfig = jsoniter.Config{
	EscapeHTML: true,
}.Froze()

func init() {
	newConfig.RegisterExtension(&customNumberExtension{})
}

func JsonDecodeUseNumber(data []byte, v interface{}) error {
	return newConfig.Unmarshal(data, v)
}

iyaozhen avatar Oct 18 '22 07:10 iyaozhen

@iyaozhen 牛!得空我测试一下看看,谢谢你!

hiscaler avatar Oct 20 '22 03:10 hiscaler