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-04GO中?分組聲明與array,?slice,?map函數(shù)
這篇文章主要介紹了GO中?分組聲明與array,slice,map函數(shù),Go語(yǔ)言中,同時(shí)聲明多個(gè)常量、變量,或者導(dǎo)入多個(gè)包時(shí),可采用分組的方式進(jìn)行聲明,下面詳細(xì)介紹需要的小伙伴可以參考一下2022-03-03golang結(jié)構(gòu)體與json格式串實(shí)例代碼
本文通過實(shí)例代碼給大家介紹了golang結(jié)構(gòu)體與json格式串的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-10-10