实现过程
- 定义Tag解析函数:解析结构体字段上的自定义标签,用于指定序列化和反序列化时的字段名等信息。
- 序列化函数:
- 使用
reflect.ValueOf
获取结构体的反射值。
- 遍历结构体字段,根据标签获取序列化字段名。
- 对于嵌套结构体,递归调用序列化函数。
- 对于接口类型,判断接口实现类型并进行相应处理。
- 反序列化函数:
- 使用
reflect.New
创建目标结构体的指针。
- 解析JSON数据,根据标签匹配字段。
- 对于嵌套结构体,递归调用反序列化函数。
- 对于接口类型,根据JSON数据中的类型信息创建具体实现类型并反序列化。
性能优化点
- 缓存反射信息:对于相同类型的结构体,缓存其反射类型信息(如字段数量、字段类型、标签等),避免每次都进行反射操作获取这些信息。
- 减少反射调用次数:在可能的情况下,尽量在循环外部进行反射操作获取必要信息,然后在循环内部使用这些信息进行常规操作。
避免反射操作常见陷阱
- 循环引用:在序列化和反序列化过程中,使用一个集合(如
map
)来记录已经处理过的对象,当再次遇到相同对象时,根据情况进行特殊处理(如在序列化时输出引用标记,反序列化时直接使用已处理对象)。
核心实现代码
package main
import (
"encoding/json"
"fmt"
"reflect"
)
// 序列化
func Serialize(obj interface{}) ([]byte, error) {
var result map[string]interface{}
value := reflect.ValueOf(obj)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
if value.Kind() != reflect.Struct {
return nil, fmt.Errorf("unsupported type")
}
result = make(map[string]interface{})
typeOf := value.Type()
for i := 0; i < value.NumField(); i++ {
field := value.Field(i)
tag := typeOf.Field(i).Tag.Get("json")
if tag == "" {
tag = typeOf.Field(i).Name
}
switch field.Kind() {
case reflect.Struct:
subResult, err := Serialize(field.Interface())
if err != nil {
return nil, err
}
result[tag] = json.RawMessage(subResult)
case reflect.Interface:
subResult, err := Serialize(field.Interface())
if err != nil {
return nil, err
}
result[tag] = json.RawMessage(subResult)
default:
result[tag] = field.Interface()
}
}
return json.Marshal(result)
}
// 反序列化
func Deserialize(data []byte, obj interface{}) error {
var rawMap map[string]json.RawMessage
err := json.Unmarshal(data, &rawMap)
if err != nil {
return err
}
value := reflect.ValueOf(obj)
if value.Kind() != reflect.Ptr || value.Elem().Kind() != reflect.Struct {
return fmt.Errorf("unsupported type")
}
value = value.Elem()
typeOf := value.Type()
for i := 0; i < value.NumField(); i++ {
field := value.Field(i)
tag := typeOf.Field(i).Tag.Get("json")
if tag == "" {
tag = typeOf.Field(i).Name
}
raw, ok := rawMap[tag]
if!ok {
continue
}
switch field.Kind() {
case reflect.Struct:
newObj := reflect.New(field.Type())
err = Deserialize(raw, newObj.Interface())
if err != nil {
return err
}
field.Set(newObj.Elem())
case reflect.Interface:
var typeInfo string
err := json.Unmarshal(raw, &typeInfo)
if err != nil {
return err
}
// 这里假设根据typeInfo能创建具体类型
newObj := reflect.New(reflect.TypeOf(typeInfo))
err = Deserialize(raw, newObj.Interface())
if err != nil {
return err
}
field.Set(newObj.Elem())
default:
err = json.Unmarshal(raw, field.Addr().Interface())
if err != nil {
return err
}
}
}
return nil
}
健壮性设计思路
- 错误处理:在序列化和反序列化过程中,对每一步可能出现的错误(如JSON解析错误、类型不支持等)都进行了详细的错误返回,方便调用者定位问题。
- 类型检查:在操作前对对象的类型进行严格检查,确保处理的类型是预期的结构体、指针等类型,避免运行时错误。
- 嵌套和接口处理:通过递归处理嵌套结构体和根据类型信息处理接口类型,确保复杂场景下的正确序列化和反序列化。