Go

Go Json 解析

Posted by maple Blog on February 2, 2016

关于Go中对json的解析有点独特的地方。

Go自带解析包,C++只能自己写,或者网上找库了 :P

import “encoding/json”

首先看下最基本的用法,

type Person struct {
	Name string
	Age  string
}
func testPerson() {
	str1 := "{\"Name\":\"hello\",\"Age\":\"15\"}"
	var ret Person
	//字符串转化为对象
	err := json.Unmarshal([]byte(str1), &ret)
	if err != nil {
		fmt.Println(err.Error())
	}
	fmt.Println(ret)
    
	//数据对象转化为字符串
	str2, err := json.Marshal(ret)
	if err != nil {
		fmt.Println(err.Error())
	}
	fmt.Println(string(str2))
}

在说说特别的地方。

type Person1 struct {
	Name string `json:"name"`
	Age  string `json:"age"`
}
func testPerson1() {
	str1 := "{\"name\":\"hello\",\"age\":\"15\"}"
	var ret Person1
    ...

这里的字符串的名字可以和定义的 struct 变量名不一致。那么这里有什么用途呢;一般来说 struct 的变量名首字母大写,方便在struct之外访问,如果不喜欢这种命名方式,非要用小写字母开头的字段名的话,可以用这种方式实现。

再补充一点,关于命名方式,在Go中的 首字母大写的 函数名,变量名,可以在包外或者结构体外访问。如果是小写字母开头的函数名,包外是不能访问的,有种C++里private的感觉。这是我的理解,有误的话,欢迎指正。:P

那么在具体使用的时候,我发现会有点不太方便的地方就是,每次在做json解析的时候,我首先得知道数据的结构,也就是说有哪些字段我事先要知道。提前定义struct。如果每次字符串的数据结构会发生变化,而我只关心里面的某个字段,或者某个数据类型很复杂,层级很深,而我只需要一小部分的字段数据。

那么可以试试这样子。 关于任意的json数据,在 Go 中可以理解为 map[string]interface {},或者[]interface {} 后者对应数组。

func testInter(str string) {
	var inter interface{}
	err := json.Unmarshal([]byte(str), &inter)
	if err != nil {
		fmt.Println(err.Error())
	}
	if GetInterType(inter) == "map[string]interface {}" {
		m := inter.(map[string]interface{})
		fmt.Println(m)
	} else if GetInterType(inter) == "[]interface {}" {
        //json数组
        arrinter := inter.([]interface{})
		for _, vv := range arrinter {
			if GetInterType(vv) != "map[string]interface {}" {
				continue
			}
			m := vv.(map[string]interface{})
			fmt.Println("arr:", m)
		}
	} else {
		fmt.Println("unknown type")
	}
}
func GetInterType(inter interface{}) string {
	aa := fmt.Sprintf("%s", reflect.TypeOf(inter))
	return aa
}
func main() {
	testInter("{\"Name\":\"hello\",\"age\":\"15\"}")
	testInter("[{\"Name\":\"hello\",\"age\":\"15\"},{\"haha\":\"word\",\"test\":\"100\"}]")
}

输出:

map[Name:hello age:15]

arr: map[Name:hello age:15]

arr: map[haha:word test:100]

通过这种方式,就可以不管任何类型的数据,这里的reflect.TypeOf(inter)还可以判断很多数据类型。。。 然后这里也涉及到了一小部分interface的用法。