您的位置:

Go结构体转JSON

一、什么是JSON

JSON(JavaScript Object Notation)是一种基于文本的轻量级数据交换格式。JSON采用完全独立于语言的文本格式来描述数据,这些特性使得JSON成为理想的数据交换语言。JSON常见于前后端数据交互,也逐渐成为替代XML的数据交换格式。

二、Go语言中的JSON支持

Go语言内置json包,提供了JSON数据的编解码功能,可直接导入使用。

import "encoding/json"

三、Go结构体转JSON

Go语言中,结构体可以通过编写tag的方法来定义该结构体的JSON格式。tag位于字段的结构体定义下方,是编译器在编译时对字段进行的描述。

通过tag的方式可以自定义JSON中的每个字段名。在tag中添加一个名为`json:"<字段名>"` 的选项即可。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    person := Person{Name: "Tom", Age: 18}
    jsonData, _ := json.Marshal(person)
    fmt.Println(string(jsonData))
}

上述代码中,我们自定义了Person的两个字段在JSON中的名称,即`name` 和 `age`。使用json.Marshal方法,将Person结构体转换为JSON格式的字符串,输出结果如下:

{"name":"Tom","age":18}

四、结构体嵌套转换为JSON

在实际应用中,结构体通常包含多个字段,甚至是嵌套结构体。在Go语言中,同样可以通过tag的方式来定义结构体的JSON格式。

type Address struct {
    Province   string `json:"province"`
    City       string `json:"city"`
    Area       string `json:"area"`
    Street     string `json:"street"`
    PostalCode string `json:"postal_code"`
}

type Person struct {
    Name    string  `json:"name"`
    Age     int     `json:"age"`
    Address Address `json:"address"`
}

func main() {
    address := Address{Province: "ZheJiang", City: "HangZhou", Area: "XiHu", Street: "WenSanLu", PostalCode: "310023"}
    person := Person{Name: "Tom", Age: 18, Address: address}
    jsonData, _ := json.Marshal(person)
    fmt.Println(string(jsonData))
}

输出结果如下:

{"name":"Tom","age":18,"address":{"province":"ZheJiang","city":"HangZhou","area":"XiHu","street":"WenSanLu","postal_code":"310023"}}

五、切片和Map转换为JSON

除了结构体,切片和Map也经常出现在JSON编解码中。和结构体一样,切片和Map的转换也需要通过tag的方式来指定键名。

type Person struct {
    Name    string              `json:"name"`
    Age     int                 `json:"age"`
    Hobbies []string            `json:"hobbies"`
    Metas   map[string]string   `json:"metas"`
}

func main() {
    person := Person{
        Name:    "Tom",
        Age:     18,
        Hobbies: []string{"coding", "running", "reading"},
        Metas:   map[string]string{"height": "184cm", "weight": "70kg"},
    }
    jsonData, _ := json.Marshal(person)
    fmt.Println(string(jsonData))
}

上述代码中,我们定义了一个Person结构体,并且包含了切片和Map类型的字段。使用json.Marshal方法,将Person结构体转换为JSON格式的字符串,输出结果如下:

{"name":"Tom","age":18,"hobbies":["coding","running","reading"],"metas":{"height":"184cm","weight":"70kg"}}

六、转换为JSON时的返回值

在编写代码的过程中,我们可能会需要知道json.Marshal方法转化后的返回值,该返回值有两种类型。

第一种类型为`[]byte`类型,表示将结构体转换为JSON格式后得到的字节序列。

jsonData, err := json.Marshal(person)
if err != nil {
    // 错误处理
}

fmt.Println(jsonData)

第二种类型为`error`类型。当转换出错时,将返回该类型的非空值。

jsonData, err := json.Marshal(person)
if err != nil {
    // 错误处理
}

fmt.Println(err)

七、从JSON转换为Go结构体

在实际开发中,还经常会遇到从JSON格式的字符串转换为Go结构体的需求。Go语言中提供了json包中的json.Unmarshal方法来完成该转换过程。

使用json.Unmarshal方法,我们需要声明一个目标类型的指针,并调用json.Unmarshal方法来实现JSON格式字符串到指定类型的转换。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    jsonStr := `{"name":"Tom","age":18}`
    person := Person{}
    err := json.Unmarshal([]byte(jsonStr), &person)
    if err != nil {
        // 错误处理
    }
    fmt.Printf("%+v", person)
}

上述代码中,我们声明了一个Person结构体的指针变量`person`作为目标类型,并使用json.Unmarshal方法将JSON字符串转换为结构体实例。输出转换后的Person对象,输出结果如下:

{Name:"Tom", Age:18}

八、小结

Go语言内置的json包提供了完善的JSON编解码功能,并且可以通过自定义tag的方式很容易地定义结构体的JSON格式。在实际开发中,我们需要熟练地掌握JSON转换的API以及tag的定义方法。同时,我们需要考虑到各种数据的可能性,避免出现一些JSON转换的异常状况。