go中利用reflect實(shí)現(xiàn)json序列化的示例代碼
利用反射實(shí)現(xiàn)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() 函數(shù)的作用是返回一個(gè)包含給定值的 reflect.Value 類型的值
拿到值 rv之后 ,使用 rv.Type().Kind() 就能拿到用戶傳入值的底層類型
rv.Type() 拿到的值是 reflect.Type 類型,沒法用來(lái)判斷,所以需要使用 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 類型可以簡(jiǎn)單理解為數(shù)組,返回的類型是數(shù)組的 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 函數(shù)
需要遍歷 slice 拿到每一項(xiàng)的內(nèi)容,可以通過 `rv.Index(i).Interface()
然后調(diào)用 jsonMarshal 函數(shù),傳入 slice 中的每一項(xiàng)內(nèi)容,遞歸處理
最后拼接出數(shù)組格式的 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 轉(zhuǎn)換為 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 類型類似于對(duì)象,返回的類型是對(duì)象的 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 函數(shù)
我們先定義一個(gè)結(jié)構(gòu)體
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
isMarraied bool `json:"is_marraied"`
}
這個(gè)結(jié)構(gòu)體中,有兩個(gè)地方需要注意:
- 小寫字母開頭的屬性,不需要序列化
- 按照
json_tag的值來(lái)序列化
通過 rv.NumField 獲取到結(jié)構(gòu)體中的所有的屬性,然后使用 for 循環(huán)遍歷
通過 rv.Field(i) 獲取到屬性的值,通過 rv.Type().Field(i).Tag.Get("json") 獲取到 json 標(biāo)簽的值
如果屬性名是小寫字母開頭的,不需要序列化,直接跳過,通過 isFieldExported 函數(shù)完成
func isFieldExported(name string) bool {
r, _ := utf8.DecodeRuneInString(name)
return unicode.IsUpper(r)
}
然后調(diào)用 jsonMarshal 函數(shù),傳入結(jié)構(gòu)體中的每一項(xiàng)內(nèi)容,遞歸處理
最后拼接出數(shù)組格式的 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轉(zhuǎn)換為slice,然后調(diào)用marshalSlice函數(shù) - 如果是
struct類型,直接調(diào)用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)
}
}
對(duì)應(yīng)的源碼:to_json
到此這篇關(guān)于go中利用reflect實(shí)現(xiàn)json序列化的示例代碼的文章就介紹到這了,更多相關(guān)go reflect json序列化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang 空map和未初始化map的注意事項(xiàng)說明
這篇文章主要介紹了Golang 空map和未初始化map的注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2021-04-04
GO中?分組聲明與array,?slice,?map函數(shù)
這篇文章主要介紹了GO中?分組聲明與array,slice,map函數(shù),Go語(yǔ)言中,同時(shí)聲明多個(gè)常量、變量,或者導(dǎo)入多個(gè)包時(shí),可采用分組的方式進(jìn)行聲明,下面詳細(xì)介紹需要的小伙伴可以參考一下2022-03-03
golang結(jié)構(gòu)體與json格式串實(shí)例代碼
本文通過實(shí)例代碼給大家介紹了golang結(jié)構(gòu)體與json格式串的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-10-10

