diff --git a/utils/math2/math.go b/utils/math2/math.go index 7a8508b..4e6d268 100644 --- a/utils/math2/math.go +++ b/utils/math2/math.go @@ -72,3 +72,12 @@ func SplitN[T constraints.Integer](v T, n int) []T { return result } + +// 除法,如果除数为0,则返回默认值 +func DivOrDefault[T constraints.Integer | constraints.Float](v, d T, def T) T { + if d == 0 { + return def + } + + return v / d +} diff --git a/utils/serder/serder.go b/utils/serder/serder.go index d3cfcd4..c665201 100644 --- a/utils/serder/serder.go +++ b/utils/serder/serder.go @@ -65,6 +65,9 @@ func JSONToObjectExRaw(data []byte, ret any) error { } // 将JSON字符串转为对象。支持TypeUnion。 +// +// 如果发现反序列化后的结果不对,但没有返回错误,可以考虑是JSON字符串有问题, +// 尤其是在反序列化嵌套的TypeUnion时,如果内部的TypeUnion反序列化失败,错误是不会传递出来的(库的缺陷) func JSONToObjectStreamEx[T any](stream io.Reader) (T, error) { var ret T dec := defaultAPI.NewDecoder(stream) diff --git a/utils/serder/serder_test.go b/utils/serder/serder_test.go index b36c0d1..abd7aef 100644 --- a/utils/serder/serder_test.go +++ b/utils/serder/serder_test.go @@ -665,3 +665,32 @@ func Test_ObjectToJSON3(t *testing.T) { // So(ret, ShouldResemble, val) }) } + +type BaseCallback interface{} +type StCallback struct { + Metadata `union:"StCallback"` + Type string + Value string +} + +func (st *StCallback) OnUnionSerializing() { + st.Value = "called" + st.Type = "StCallback" +} + +func Test_ObjectToJSONEx4(t *testing.T) { + Convey("序列化Callback", t, func() { + union := types.NewTypeUnion[BaseCallback](&StCallback{}) + UseTypeUnionInternallyTagged(&union, "Type") + + val := []BaseCallback{&StCallback{}} + data, err := ObjectToJSONEx(val) + So(err, ShouldBeNil) + + ret, err := JSONToObjectEx[[]BaseCallback](data) + So(err, ShouldBeNil) + + So(len(ret), ShouldEqual, 1) + So(ret[0].(*StCallback).Value, ShouldEqual, "called") + }) +} diff --git a/utils/serder/types/types.go b/utils/serder/types/types.go index 0046926..a1cd975 100644 --- a/utils/serder/types/types.go +++ b/utils/serder/types/types.go @@ -1,3 +1,7 @@ package types type Metadata struct{} + +type OnUnionSerializing interface { + OnUnionSerializing() +} diff --git a/utils/serder/union_handler.go b/utils/serder/union_handler.go index cd98a02..dd6fb16 100644 --- a/utils/serder/union_handler.go +++ b/utils/serder/union_handler.go @@ -8,6 +8,7 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/modern-go/reflect2" "gitlink.org.cn/cloudream/common/pkgs/types" + sertypes "gitlink.org.cn/cloudream/common/utils/serder/types" ref2 "gitlink.org.cn/cloudream/common/utils/reflect2" ) @@ -211,6 +212,12 @@ func (e *InternallyTaggedEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.St val = reflect2.IFaceToEFace(ptr) } + if val != nil { + if on, ok := val.(sertypes.OnUnionSerializing); ok { + on.OnUnionSerializing() + } + } + // 可以考虑检查一下Type字段有没有赋值,没有赋值则将其赋值为union Tag指定的值 stream.WriteVal(val) } @@ -292,6 +299,10 @@ func (e *ExternallyTaggedEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.St return } + if on, ok := val.(sertypes.OnUnionSerializing); ok { + on.OnUnionSerializing() + } + stream.WriteObjectStart() valType := ref2.TypeOfValue(val) if !e.union.Union.Include(valType) {