go中利用reflect实现json序列化的示例代码

2024-04-18 0 527
目录
  • 判断 int 类型
  • 判断 float 类型
  • 判断 string 类型
  • 判断 bool 类型
  • 判断 slice 类型
  • 判断 array 类型
  • 判断 struct 类型
  • 处理 pointer 类型

利用反射实现json序列化

type Person struct {
Name string `json:\”name\”`
Age int `json:\”age\”`
IsMarraied bool `json:\”is_marraied\”`
}
k := map[int]Person{
1: {Name: \”uccs\”, Age: 18, IsMarraied: false},
2: {Name: \”uccs\”, Age: 18, IsMarraied: true},
3: {Name: \”uccs\”, Age: 18, IsMarraied: true},
}

s := &[…]interface{}{
1,
&Person{Name: \”uccs\”, Age: 18, IsMarraied: false},
Person{Name: \”uccs\”, Age: 18, IsMarraied: true},
true,
Person{Name: \”uccs\”, Age: 18, IsMarraied: true},
}

reflect.ValueOf() 函数的作用是返回一个包含给定值的 reflect.Value 类型的值

拿到值 rv之后 ,使用 rv.Type().Kind() 就能拿到用户传入值的底层类型

rv.Type() 拿到的值是 reflect.Type 类型,没法用来判断,所以需要使用 rv.Type().Kind() 拿到 reflect.Kind

判断 int 类型

int 类型有 int、int8、int16、int32、int64,返回 fmt.Sprintf("%v", rv.Int())

func JsonMarshal(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
rt := rv.Type()
switch rt.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return fmt.Sprintf(\”%v\”, rv.Int()), nil
default:
return \”\”, fmt.Errorf(\”unsupported type: %s\”, rt)
}
}

判断 float 类型

float类型有float32和float64,返回fmt.Sprintf("%v", rv.Float())

func JsonMarshal(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
rt := rv.Type()
switch rt.Kind() {
case reflect.Float32, reflect.Float64:
return fmt.Sprintf(\”%v\”, rv.Float()), nil
default:
return \”\”, fmt.Errorf(\”unsupported type: %s\”, rt)
}
}

判断 string 类型

string类型,返回fmt.Sprintf("%q", rv.String())

func JsonMarshal(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
rt := rv.Type()
switch rt.Kind() {
case reflect.String:
return fmt.Sprintf(\”%q\”, rv.String()), nil
default:
return \”\”, fmt.Errorf(\”unsupported type: %s\”, rt)
}
}

判断 bool 类型

bool类型,返回fmt.Sprintf("%v", rv.Bool())

func JsonMarshal(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
rt := rv.Type()
switch rt.Kind() {
case reflect.Bool:
return fmt.Sprintf(\”%v\”, rv.Bool()), nil
default:
return \”\”, fmt.Errorf(\”unsupported type: %s\”, rt)
}
}

判断 slice 类型

slice类型可以简单理解为数组,返回的类型是数组的json字符串

func JsonMarshal(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
rt := rv.Type()
switch rt.Kind() {
case reflect.Slice:
return marshalSlice(rv)
default:
return \”\”, fmt.Errorf(\”unsupported type: %s\”, rt)
}
}

处理 slice 的过程封装为 marshalSlice 函数

需要遍历 slice 拿到每一项的内容,可以通过 `rv.Index(i).Interface()

然后调用 jsonMarshal 函数,传入 slice 中的每一项内容,递归处理

最后拼接出数组格式的 json 字符串,使用 strings.Join(items, ",") 拼接

func marshalSlice(rv reflect.Value) (string, error) {
var items []string
for i := 0; i < rv.Len(); i++ {
value, err := JsonMarshal(rv.Index(i).Interface())
if err != nil {
return \”\”, err
}
items = append(items, value)
}
return \”[\” + strings.Join(items, \”,\”) + \”]\”, nil
}

判断 array 类型

处理array类型和处理slice是一样的,只需要将array转换为slice,在反射中可以使用rv.Slice(0, rv.Len())

func JsonMarshal(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
rt := rv.Type()
switch rt.Kind() {
case reflect.Array:
return marshalSlice(rv.Slice(0, rv.Len()))
default:
return \”\”, fmt.Errorf(\”unsupported type: %s\”, rt)
}
}

判断 struct 类型

struct类型类似于对象,返回的类型是对象的json字符串

func JsonMarshal(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
rt := rv.Type()
switch rt.Kind() {
case reflect.Struct:
return marshalStruct(rv)
default:
return \”\”, fmt.Errorf(\”unsupported type: %s\”, rt)
}
}

处理struct的过程封装为marshalStruct函数

我们先定义一个结构体

type Person struct {
Name string `json:\”name\”`
Age int `json:\”age\”`
isMarraied bool `json:\”is_marraied\”`
}

这个结构体中,有两个地方需要注意:

  • 小写字母开头的属性,不需要序列化
  • 按照 json_tag 的值来序列化

通过 rv.NumField 获取到结构体中的所有的属性,然后使用 for 循环遍历

通过 rv.Field(i) 获取到属性的值,通过 rv.Type().Field(i).Tag.Get("json") 获取到 json 标签的值

如果属性名是小写字母开头的,不需要序列化,直接跳过,通过 isFieldExported 函数完成

func isFieldExported(name string) bool {
r, _ := utf8.DecodeRuneInString(name)
return unicode.IsUpper(r)
}

然后调用jsonMarshal函数,传入结构体中的每一项内容,递归处理

最后拼接出数组格式的json字符串,使用strings.Join(items, ",")拼接

func marshalStruct(rv reflect.Value) (string, error) {
var items []string
for i := 0; i < rv.NumField(); i++ {
fieldValue := rv.Field(i)
jsonTag := rv.Type().Field(i).Tag.Get(\”json\”)
key := rv.Type().Field(i).Name
if !isFieldExported(key) {
continue
}
if jsonTag != \”\” {
key = jsonTag
}
value, err := JsonMarshal(fieldValue.Interface())
if err != nil {
return \”\”, err
}

items = append(items, fmt.Sprintf(\”%q:%v\”, key, value))
}
return \”{\” + strings.Join(items, \”,\”) + \”}\”, nil
}

处理 pointer 类型

处理 pointer 类型,需要先判断 pointer 指向的类型

  • 如果是 array 类型,需要将 pointer 转换为 slice,然后调用 marshalSlice 函数
  • 如果是 struct 类型,直接调用 marshalStruct

func JsonMarshal(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
rt := rv.Type()
switch rt.Kind() {
case reflect.Pointer:
if rv.Elem().Kind() == reflect.Array {
return marshalSlice(rv.Elem().Slice(0, rv.Len()))
}
if rv.Elem().Kind() == reflect.Struct {
return JsonMarshal(rv.Elem().Interface())
}
return JsonMarshal(rv.Elem().Interface())
default:
return \”\”, fmt.Errorf(\”unsupported type: %s\”, rt)
}
}

对应的源码:to_json

到此这篇关于go中利用reflect实现json序列化的示例代码的文章就介绍到这了,更多相关goreflectjson序列化内容请搜索悠久资源网以前的文章或继续浏览下面的相关文章希望大家以后多多支持悠久资源网!

您可能感兴趣的文章:

  • 解决Go Json Unmarshal反序列化丢失数字精度问题
  • Gojson反序列化“null“的问题解决
  • Go语言对JSON数据进行序列化和反序列化
  • 自定义Go Json的序列化方法译文
  • Golang中Json的序列化和反序列化的使用

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悠久资源 Golang go中利用reflect实现json序列化的示例代码 https://www.u-9.cn/jiaoben/golang/187495.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务