From a1e7662b26d8a2900f9dc4bbd9d30862747ea7e5 Mon Sep 17 00:00:00 2001 From: pro911 <23956580@qq.com> Date: Wed, 29 Oct 2025 16:27:07 +0800 Subject: [PATCH] =?UTF-8?q?:art:=20=E6=8F=90=E4=BA=A4=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binding/form_mapping.go | 21 +++ codec/json/jsoniter.go | 280 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+) diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 45a39e15..35bf0b3c 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -347,10 +347,31 @@ func setWithProperType(val string, value reflect.Value, field reflect.StructFiel return nil } +func containsAF(s string) bool { + for _, char := range s { + if char >= 'a' && char <= 'f' { + return true + } + } + return false +} + func setIntField(val string, bitSize int, field reflect.Value) error { if val == "" { val = "0" } + + //TODO 校验数据是否是16进制雪花id如果是则将期转为int64 start + if bitSize == 64 && (len(val) < 17 || containsAF(val)) { + //hack for hex,must 16位 + intVal, err := strconv.ParseInt(val, 16, 64) + if err != nil { + field.SetInt(intVal) + } + return err + } + //TODO end + intVal, err := strconv.ParseInt(val, 10, bitSize) if err == nil { field.SetInt(intVal) diff --git a/codec/json/jsoniter.go b/codec/json/jsoniter.go index ea624e77..847e42c3 100644 --- a/codec/json/jsoniter.go +++ b/codec/json/jsoniter.go @@ -15,7 +15,287 @@ import ( // Package indicates what library is being used for JSON encoding. const Package = "github.com/json-iterator/go" +func containsAF(s string) bool { + for _, char := range s { + if char >= 'a' && char <= 'f' { + return true + } + } + return false +} + +// HexStringEncoder 自定义编码器将 int64 类型编码为十六进制字符串或者把16进制转为int64 +type HexStringEncoder struct { + IsInt64Pointer bool //源数据为 *int64 +} + +// Encode 实现 jsoniter.ValEncoder 接口 +func (e *HexStringEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) { + if ptr == nil { + stream.WriteNil() + return + } + + // Convert *int64 value to a 16-byte hexadecimal string + if e.IsInt64Pointer { + pp := (**int64)(ptr) + if *pp == nil { + stream.WriteNil() + return + } + stream.WriteString(fmt.Sprintf("%x", **pp)) + return + } + + // Convert int64 value to a 16-byte hexadecimal string + value := *(*int64)(ptr) + if value == 0 { + stream.WriteString("0") //0值特殊处理 + } else { + stream.WriteString(fmt.Sprintf("%x", value)) + } +} + +func (e *HexStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return ptr == nil || *(*int64)(ptr) == 0 +} + +func (codec *HexStringEncoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + valueType := iter.WhatIsNext() + if valueType == jsoniter.StringValue { + str := iter.ReadString() + var i int64 + var err error + if len(str) < 17 || containsAF(str) { + i, err = strconv.ParseInt(str, 16, 64) + if err != nil { + i = 0 + } + } else { + i, err = strconv.ParseInt(str, 10, 64) + if err != nil { + i = 0 + } + } + + *((*int64)(ptr)) = i + } else if valueType == jsoniter.NumberValue { + *((*int64)(ptr)) = iter.ReadInt64() + } else { + *((*int64)(ptr)) = 0 + } +} + +// EmptyObjectEncoder 实现一个编码器,当字段值为nil时,写入空对象{} +type EmptyObjectEncoder struct { + encoder jsoniter.ValEncoder +} + +func (encoder *EmptyObjectEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) { + // If the pointer points to nil, write an empty object. + if *(*uintptr)(ptr) == 0 { + stream.WriteRaw("{}") + return + } + // Fallback to default encoding. + encoder.encoder.Encode(ptr, stream) +} + +func (encoder *EmptyObjectEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(ptr) +} + +type EmptyArrayEncoder struct { + encoder jsoniter.ValEncoder +} + +func (encoder *EmptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) { + // If the pointer points to nil, write an empty object. + if *(*uintptr)(ptr) == 0 { + stream.WriteRaw("[]") + return + } + // Fallback to default encoding. + encoder.encoder.Encode(ptr, stream) +} + +func (encoder *EmptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(ptr) +} + +// 空数组64位数组 +type EmptyArrayInt64Encoder struct { + encoder jsoniter.ValEncoder + decoder jsoniter.ValDecoder +} + +func (encoder *EmptyArrayInt64Encoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) { + // If the pointer points to nil, write an empty object. + if *(*uintptr)(ptr) == 0 { + stream.WriteRaw("[]") + return + } + + //循环数组 + slice := (*[]int64)(ptr) + strSlice := make([]string, len(*slice)) + for i, v := range *slice { + if v == 0 { + strSlice[i] = "0" + } else { + strSlice[i] = fmt.Sprintf("%x", v) + } + } + + jsonData, err := jsonInstance.Marshal(strSlice) + if err != nil { + encoder.encoder.Encode(ptr, stream) + return + } + stream.WriteRaw(string(jsonData)) +} + +func (codec *EmptyArrayInt64Encoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + //str := iter.ReadString() + valueList := []int64{} + for iter.ReadArray() { + val := iter.Read() + if iter.Error != nil { + break + } + + if str, ok := val.(string); ok { + //含有a-f或者正好16位使用16进制解析 + if len(str) < 17 || containsAF(str) { + intVal, err := strconv.ParseInt(str, 16, 64) + if err != nil { + continue + } + valueList = append(valueList, intVal) + } else { + intVal, err := strconv.ParseInt(str, 10, 64) + if err != nil { + continue + } + valueList = append(valueList, intVal) + } + } + } + + // 将ptr解析为*[]int64类型的指针 + ptrToSlice := (*[]int64)(ptr) + // 使用reflect包将ptr的内容替换为slice + reflect.ValueOf(ptrToSlice).Elem().Set(reflect.ValueOf(valueList)) +} + +func (encoder *EmptyArrayInt64Encoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(ptr) +} + +type ToStringEncoder struct{} + +func (codec *ToStringEncoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + valueType := iter.WhatIsNext() + if valueType == jsoniter.StringValue { + str := iter.ReadString() + *((*string)(ptr)) = str + } else { + valueAsString := iter.ReadAny().ToString() + *((*string)(ptr)) = valueAsString + } +} + +type ToBoolEncoder struct { + decoder jsoniter.ValDecoder + DefaultVal bool +} + +func (codec *ToBoolEncoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + valueType := iter.WhatIsNext() + if valueType == jsoniter.BoolValue { + codec.decoder.Decode(ptr, iter) + } else if valueType == jsoniter.NumberValue { + i := iter.ReadInt() + var myBool bool + if i > 0 { + myBool = true + } else { + myBool = false + } + *((*bool)(ptr)) = myBool + } else if valueType == jsoniter.StringValue { + str := strings.ToLower(iter.ReadString()) + var myBool bool + if str == "true" || str == "1" { + myBool = true + } else if str == "false" || str == "0" || str == "-1" { + myBool = false + } else { + myBool = codec.DefaultVal + } + *((*bool)(ptr)) = myBool + } else { + str := strings.ToLower(iter.ReadAny().ToString()) + var myBool bool + if str == "true" || str == "1" { + myBool = true + } else if str == "false" || str == "0" || str == "-1" { + myBool = false + } else { + myBool = codec.DefaultVal + } + *((*bool)(ptr)) = myBool + } +} + +// HexStringExtension 检查 struct 字段tags,为相应的 int64 字段应用 HexStringEncoder +type ApipostExtension struct { + jsoniter.DummyExtension +} + +// UpdateStructDescriptor 修改 struct 字段的编码/解码器 +func (extension *ApipostExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) { + for _, binding := range structDescriptor.Fields { + // 检查字段类型和 tag + if binding.Field.Type().Kind() == reflect.Int64 { + //处理64位转换 + if strings.Contains(binding.Field.Tag().Get("json"), "hexstring") { + binding.Encoder = &HexStringEncoder{} + binding.Decoder = &HexStringEncoder{} + } + } else if binding.Field.Type().Kind() == reflect.Ptr || binding.Field.Type().Kind() == reflect.Interface { + if strings.Contains(binding.Field.Tag().Get("json"), "hexstring") && binding.Field.Type().Type1().Elem().Kind() == reflect.Int64 { //处理*int64位转换 + binding.Encoder = &HexStringEncoder{IsInt64Pointer: true} + } else if strings.Contains(binding.Field.Tag().Get("json"), "emptyobject") { //处理空对象 + binding.Encoder = &EmptyObjectEncoder{binding.Encoder} + } + } else if binding.Field.Type().Kind() == reflect.Slice || binding.Field.Type().Kind() == reflect.Array { + //处理空数组 + if binding.Field.Type().Type1().Elem().String() == "int64" { + //强制转64数组 + int64SliceEncode := &EmptyArrayInt64Encoder{binding.Encoder, binding.Decoder} + binding.Encoder = int64SliceEncode + binding.Decoder = int64SliceEncode + } else if strings.Contains(binding.Field.Tag().Get("json"), "emptyarray") { + binding.Encoder = &EmptyArrayEncoder{binding.Encoder} + } + } else if binding.Field.Type().Kind() == reflect.String { + if strings.Contains(binding.Field.Tag().Get("json"), "tostring") { + binding.Decoder = &ToStringEncoder{} + } + } else if binding.Field.Type().Kind() == reflect.Bool { + tagStr := binding.Field.Tag().Get("json") + if strings.Contains(tagStr, "tofalse") { + binding.Decoder = &ToBoolEncoder{binding.Decoder, false} + } else if strings.Contains(tagStr, "totrue") { + binding.Decoder = &ToBoolEncoder{binding.Decoder, true} + } + } + } +} + func init() { + json.RegisterExtension(&ApipostExtension{}) API = jsoniterApi{} }