Go解析JSON:实现结构化解析与自定义属性映射
2023-11-26 10:47:20
Go 语言解析 JSON 的多种方式
Go 语言提供了多种解析 JSON 的方法,每种方法都有其特定的优缺点。在本文中,我们将重点介绍两种最常用的方法:使用内置的 encoding/json
包和使用第三方库 jsoniter
。
使用 encoding/json
包解析 JSON
encoding/json
包是 Go 语言标准库的一部分,提供了解析 JSON 数据的内置功能。它使用简单,但效率可能较低,尤其是在处理大型 JSON 数据时。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
// 定义 JSON 字符串
jsonStr := `{"name": "John", "age": 30}`
// 创建一个 Person 类型的变量
var person Person
// 使用 json.Unmarshal() 函数将 JSON 字符串解析为 Person 结构体
err := json.Unmarshal([]byte(jsonStr), &person)
if err != nil {
fmt.Println("Error:", err)
return
}
// 打印 Person 结构体的字段值
fmt.Println("Name:", person.Name)
fmt.Println("Age:", person.Age)
}
使用 jsoniter
库解析 JSON
jsoniter
是一个第三方库,专门用于解析 JSON 数据。它比 encoding/json
包效率更高,并且提供了更多高级特性,如支持非结构化 JSON 数据解析。
package main
import (
"fmt"
"github.com/json-iterator/go"
)
type Person struct {
Name string
Age int
}
func main() {
// 定义 JSON 字符串
jsonStr := `{"name": "John", "age": 30}`
// 创建一个 Person 类型的变量
var person Person
// 使用 jsoniter.Unmarshal() 函数将 JSON 字符串解析为 Person 结构体
iter := jsoniter.ParseString(jsonStr)
err := iter.ToVal(&person)
if err != nil {
fmt.Println("Error:", err)
return
}
// 打印 Person 结构体的字段值
fmt.Println("Name:", person.Name)
fmt.Println("Age:", person.Age)
}
解析 JSON 中的数组
解析 JSON 数组与解析 JSON 对象非常相似。您需要定义一个结构体来表示数组中的元素,然后使用 encoding/json
包或 jsoniter
库中的 Unmarshal()
函数将 JSON 数组解析为结构体数组。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
// 定义 JSON 字符串
jsonStr := `[
{"name": "John", "age": 30},
{"name": "Mary", "age": 25}
]`
// 创建一个 Person 类型的数组
var persons []Person
// 使用 json.Unmarshal() 函数将 JSON 数组解析为 Person 结构体数组
err := json.Unmarshal([]byte(jsonStr), &persons)
if err != nil {
fmt.Println("Error:", err)
return
}
// 遍历 Person 结构体数组并打印每个元素的字段值
for _, person := range persons {
fmt.Println("Name:", person.Name)
fmt.Println("Age:", person.Age)
}
}
解析 JSON 中的嵌入对象
如果 JSON 数据包含嵌入对象,您可以使用嵌套结构体来表示这些对象。例如,以下 JSON 数据包含了一个嵌套的 Address
对象:
{
"name": "John",
"age": 30,
"address": {
"street": "123 Main Street",
"city": "Anytown",
"state": "CA",
"zip": "12345"
}
}
您可以使用以下代码来解析这个 JSON 数据:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
Address Address
}
type Address struct {
Street string
City string
State string
Zip string
}
func main() {
// 定义 JSON 字符串
jsonStr := `{
"name": "John",
"age": 30,
"address": {
"street": "123 Main Street",
"city": "Anytown",
"state": "CA",
"zip": "12345"
}
}`
// 创建一个 Person 类型的变量
var person Person
// 使用 json.Unmarshal() 函数将 JSON 字符串解析为 Person 结构体
err := json.Unmarshal([]byte(jsonStr), &person)
if err != nil {
fmt.Println("Error:", err)
return
}
// 打印 Person 结构体的字段值
fmt.Println("Name:", person.Name)
fmt.Println("Age:", person.Age)
fmt.Println("Address:", person.Address)
}
解析 JSON 中的自定义属性名称
有时,您可能需要将 JSON 数据中的属性名称映射到结构体中的不同名称。这可以通过使用 json:"property_name"
标签来实现。例如,以下代码将 first_name
属性映射到 Name
字段,将 last_name
属性映射到 LastName
字段:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"first_name"`
LastName string `json:"last_name"`
}
func main() {
// 定义 JSON 字符串
jsonStr := `{"first_name": "John", "last_name": "Doe"}`
// 创建一个 Person 类型的变量
var person Person
// 使用 json.Unmarshal() 函数将 JSON 字符串解析为 Person 结构体
err := json.Unmarshal([]byte(jsonStr), &person)
if err != nil {
fmt.Println("Error:", err)
return
}
// 打印 Person 结构体的字段值
fmt.Println("Name:", person.Name)
fmt.Println("Last Name:", person.LastName)
}
解析非结构化 JSON 字符串
有时,您可能需要解析非结构化的 JSON 字符串,即不是由键值对组成的 JSON 数据。这可以通过使用 json.RawMessage
类型来实现。例如,以下代码将 JSON 字符串解析为 json.RawMessage
类型:
package main
import (
"encoding/json"
"fmt"
)
func main() {
// 定义 JSON 字符串
jsonStr := `["John", "Mary", "Bob"]`
// 创建一个 json.RawMessage 类型的变量
var data json.RawMessage
// 使用 json.Unmarshal() 函数将 JSON 字符串解析为 json.RawMessage 类型
err := json.Unmarshal([]byte(jsonStr), &data)
if err != nil {
fmt.Println("Error:", err)
return
}
// 打印 json.RawMessage 类型的变量
fmt.Println(string(data))
}
结论
Go 语言提供了多种方法来解析 JSON 数据。您可以选择使用内置的 encoding/json
包或第三方库 jsoniter
。解析 JSON 数据时,您可以定义结构体来表示 JSON 对象和数组,并使用嵌套结构体来表示嵌入对象。您还可以使用 json:"property_name"
标签来将 JSON 数据中的属性名称映射到结构体中的不同名称。如果您需要解析非结构化的 JSON 字符串,可以使用 json.RawMessage
类型。