go中利用reflect实现json序列化的示例代码
作者:uccs
利用反射实现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序列化的示例代码的文章就介绍到这了,更多相关go reflect json序列化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!