这段代码实现了一个简单的 JSON 序列化和反序列化功能。代码包括一个 User
结构体和两个函数 Marshal
和 UnMarshal
,分别用于将数据转换为 JSON 格式和将 JSON 格式的数据解析回结构体。
package mainimport ("bytes""fmt""reflect""strconv""strings"
)// User 定义了一个用户结构体,其中包含名称、年龄和性别字段
type User struct {Name stringAge stringSex byte `json:"gender"` // 使用 json 标签自定义字段名
}// Marshal 将任意类型 v 序列化为 JSON 格式的字节数组
func Marshal(v interface{}) ([]byte, error) {value := reflect.ValueOf(v) // 获取值的反射对象typ := value.Type() // 获取值的类型bf := bytes.Buffer{} // 使用 bytes.Buffer 以高效地构造 JSON 字符串switch typ.Kind() {case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int8, reflect.Int64, reflect.Uint8:// 对于整数类型,将其转换为字符串并返回字节数组return []byte(fmt.Sprintf("%v", value.Interface())), nilcase reflect.String:// 对于字符串类型,将其加上双引号后返回字节数组return []byte("\"" + value.String() + "\""), nilcase reflect.Bool:// 对于布尔值,将其转换为 "true" 或 "false" 字符串return []byte(fmt.Sprintf("%t", value.Bool())), nilcase reflect.Float32, reflect.Float64:// 对于浮点数类型,将其转换为字符串并返回字节数组return []byte(fmt.Sprintf("%f", value.Float())), nilcase reflect.Struct:// 对于结构体类型,构造 JSON 格式的字符串bf.WriteByte('{')if value.NumField() > 0 {for i := 0; i < value.NumField(); i++ {fieldValue := value.Field(i) // 获取字段值fieldType := typ.Field(i) // 获取字段类型if fieldType.IsExported() {// 处理导出字段name := fieldType.Nameif len(fieldType.Tag.Get("json")) > 0 {// 使用 JSON 标签指定的字段名name = fieldType.Tag.Get("json")}bf.WriteByte('"')bf.WriteString(name)bf.WriteByte('"')bf.WriteByte(':')if bs, err := Marshal(fieldValue.Interface()); err == nil {bf.Write(bs)} else {return nil, err}bf.WriteByte(',')}}bf.Truncate(len(bf.Bytes()) - 1) // 删除最后一个逗号}bf.WriteByte('}')return bf.Bytes(), nildefault:// 对于不支持的类型,返回错误return nil, fmt.Errorf("暂不支持该类型%s", typ.Kind())}
}// UnMarshal 将 JSON 格式的字节数组 data 解析为类型为 v 的值
func UnMarshal(v interface{}, data []byte) error {value := reflect.ValueOf(v) // 获取值的反射对象typ := value.Type() // 获取值的类型if typ.Kind() != reflect.Ptr {return fmt.Errorf("必须为指针")} else {typ = typ.Elem() // 获取指针指向的类型value = value.Elem() // 获取指针指向的值}s := string(data) // 将字节数组转换为字符串switch typ.Kind() {case reflect.Int:// 解析整数if i, err := strconv.ParseInt(s, 10, 64); err == nil {value.SetInt(i) // 设置解析后的整数值} else {return err}case reflect.Uint8:// 解析无符号整数(字节)if i, err := strconv.ParseUint(s, 10, 64); err == nil {value.SetUint(i) // 设置解析后的字节值} else {return err}case reflect.Bool:// 解析布尔值if b, err := strconv.ParseBool(s); err == nil {value.SetBool(b) // 设置解析后的布尔值} else {return err}case reflect.Float32:// 解析浮点数if f, err := strconv.ParseFloat(s, 64); err == nil {value.SetFloat(f) // 设置解析后的浮点数值} else {return err}case reflect.String:// 解析字符串,确保字符串被双引号包围if s[0] == '"' && s[len(s)-1] == '"' {value.SetString(s[1 : len(s)-1]) // 去掉双引号} else {return fmt.Errorf("json格式不对")}case reflect.Struct:// 解析结构体if s[0] == '{' && s[len(s)-1] == '}' {arr := strings.Split(s[1:len(s)-1], ",") // 去掉大括号并拆分字段if len(arr) > 0 {fieldCount := typ.NumField()tag2Field := make(map[string]string, fieldCount)for i := 0; i < fieldCount; i++ {fieldType := typ.Field(i)name := fieldType.Nameif len(fieldType.Tag.Get("json")) > 0 {// 使用 JSON 标签指定的字段名name = fieldType.Tag.Get("json")}tag2Field[name] = fieldType.Name}for _, ele := range arr {brr := strings.SplitN(ele, ":", 2) // 拆分标签和数据tag := brr[0]if tag[0] == '"' && tag[len(tag)-1] == '"' {tag = tag[1 : len(tag)-1]if fieldName, exists := tag2Field[tag]; exists {fieldValue := value.FieldByName(fieldName)fieldType := fieldValue.Type()if fieldValue.Kind() != reflect.Ptr {fieldValue = fieldValue.Addr()if err := UnMarshal(fieldValue.Interface(), []byte(brr[1])); err != nil {return err}} else {newValue := reflect.New(fieldType.Elem())if err := UnMarshal(newValue.Interface(), []byte(brr[1])); err != nil {return err} else {fieldValue.Set(newValue)}}}} else {return fmt.Errorf("json格式不对%s", tag)}}}} else {return fmt.Errorf("格式错误")}default:// 对于不支持的类型,返回错误return fmt.Errorf("暂不支持该数据类型%s", typ.Kind())}return nil
}// main 函数演示了如何使用 Marshal 和 UnMarshal 函数
func main() {user := User{Name: "ffff5",Age: "35",Sex: 1,}if date, err := Marshal(user); err == nil {fmt.Println(string(date)) // 打印序列化后的 JSON 字符串var u2 = userif err := UnMarshal(&u2, date); err == nil {fmt.Println(u2.Name, u2.Age, u2.Sex) // 打印反序列化后的数据} else {fmt.Println(err) // 打印错误信息}} else {fmt.Println(err) // 打印序列化错误}
}
-
User
结构体:- 定义了一个包含
Name
(名称)、Age
(年龄)和Sex
(性别)字段的结构体。 Sex
字段使用了json
标签来指定 JSON 中的字段名为"gender"
。
- 定义了一个包含
-
Marshal
函数:- 将传入的任意类型的值转换为 JSON 格式的字节数组。
- 支持整数、字符串、布尔值、浮点数和结构体。
- 对于结构体,处理字段标签和序列化字段值。
-
UnMarshal
函数:- 将 JSON 格式的字节数组解析为传入指针类型
v
所指向的值。 - 支持整数、字节(无符号 8 位整数)、布尔值、浮点数、字符串和结构体。
- 处理 JSON 格式,支持通过标签来解析结构体字段。
- 将 JSON 格式的字节数组解析为传入指针类型
-
main
函数:- 创建一个
User
对象,并将其序列化为 JSON。 - 将序列化后的 JSON 字符串反序列化为新的
User
对象,并打印结果。
- 创建一个