mirror of
https://github.com/gin-gonic/gin.git
synced 2025-12-11 19:47:00 +08:00
🎨 提交支持逻辑
This commit is contained in:
parent
6ad6205e9c
commit
a1e7662b26
@ -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)
|
||||
|
||||
@ -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{}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user