本文将阐明如何利用 Go 语言将 JSON 解析为构造体和数组,如果解析 JSON 的嵌入对象,如何将 JSON 的自定义属性名称映射到构造体,如何解析非结构化的 JSON 字符串。
JSON 解析为构造体
JSON 的构造是 key-value,最直观的就是将 JSON 解析为构造体,如下 JSON:
{
"name": yuzhou1u,
"age": 18
}
Go 语言中,提供了一个专门的包 encoding/json
,所以咱们在应用这个 JSON 包之前须要在头文件导入:
package main
import (
"encoding/json"
"fmt"
)
而后,咱们须要定义一个 Go 语言的构造体以便咱们能与 JSON 一一对应,比方在 JSON 中咱们定义了姓名 name
和年龄 age
,所以须要定义一个构造体(命名能够随便,但最好通俗易懂)的字段与 JSON 字符串中的键相匹配:
type Person struct {
Name string
Age int
}
而后应用 json.Umarshal()
函数来解析 JSON 字符串,残缺代码如下:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
var p Person
jsonString := `{"name": "yuzhou1su",
"age" : 18}`
err := json.Unmarshal([]byte(jsonString), &p)
if err == nil {fmt.Println(p.Name)
fmt.Println(p.Age)
} else {fmt.Println(err)
}
}
当初来解释一下下面 main 函数的代码:
- 定义一个 Person 的 p 对象
- 因为咱们没有把文件系统应用上,所以是定义了一个
jsonString
的 JSON 数据 - 应用
json.Unmarshal()
函数可能解析 JSON 格局的数据。但须要将 JSON 字符串转换为字节切片,并将后果存储到 p 对象中。应用须要应用 & 地址运算符传入人员的地址。 - 如果解析无效,则
json.Unmarshal()
函数返回 nil,您当初能够找到存储在 person 变量中的值。 - 确保将 Person 构造中每个字段的第一个字符大写。如果字段名称以小写字母结尾,则不会导出到以后包之外,并且字段对
json.Unmarshal()
函数不可见。
运行上述代码,打印在控制台中后果为:
yuzhou1su
18
JSON 解析为数组
通常 JSON 数据会包含一系列的对象数组,就像这样一个班级的数据:
[
{
"id": 1,
"name": "张三"
"age": 20
},
{
"id": 2,
"name": "李翠花"
"age": 18
},
{
"id": 3,
"name": "王老五"
"age": 25
}
]
咱们只须要定义一个 students[]
的数组,代码如下:
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Id int
Name string
Age int
}
func main() {var students []Student
myClass :=
`[
{
"id": 1,
"name": "张三",
"age": 20
},
{
"id": 2,
"name": "李翠花",
"age": 18
},
{
"id": 3,
"name": "王老五",
"age": 25
}
]`
err := json.Unmarshal([]byte(myClass), &students)
if err == nil {
for _, student := range students {fmt.Print("\t\n", student.Id)
fmt.Print("\t", student.Name)
fmt.Print("\t", student.Age)
}
} else {fmt.Println(err)
}
}
应用 for...range
迭代数组,而后运行上述代码:
$ go run main.go
1 张三 20
2 李翠花 18
3 王老五 25
解析 JSON 嵌入对象
JSON 字符串有时蕴含嵌入对象,比方:
{
"name": "yuzhou1su",
"age": 18,
"address": {
"road": "renmin south road",
"street": "123 street",
"city": "cs",
"province": "hn",
"country": "cn"
}
}
address
就是属于内嵌对象,咱们同样须要创立另一个 Address
构造体:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
Address struct {
Road string
Street string
City string
Province string
Country string
}
}
func main() {
var p Person
jsonString := `
{
"name": "yuzhou1su",
"age": 18,
"address": {
"road": "renmin south road",
"street": "123 street",
"city": "cs",
"province": "hn",
"country": "cn"
}
}`
err := json.Unmarshal([]byte(jsonString), &p)
if err == nil {fmt.Println(p.Name)
fmt.Println(p.Age)
fmt.Println(p.Address.Road)
fmt.Println(p.Address.Street)
fmt.Println(p.Address.City)
fmt.Println(p.Address.Province)
fmt.Println(p.Address.Country)
} else {fmt.Println(err)
}
}
输入后果:
yuzhou1su
18
renmin south road
123 street
cs
hn
cn
自定义属性名称的映射
有时 JSON 字符串中的键不能间接映射到 Go 中构造的成员。比方:
{
"base currency": "USD",
"destination currency": "CNY"
}
请留神,此 JSON 字符串中的键中有空格。如果你尝试将它间接映射到一个构造,你会遇到问题,因为 Go 中的变量名不能有空格。要解决此问题,您能够应用构造字段标记(在构造中的每个字段之后搁置的字符串文字),如下所示:
type Rates stuct {
Base string `json:"base currency"`
Symbol string `json:"destination currency"`
}
- JSON 的
base currency
映射到 Go 中的Base
字段 - JSON 的
destination currency
映射到 Go 中Symbol
整合如下:
package main
import (
"encoding/json"
"fmt"
)
type Rates struct {
Base string `json:"base currency"`
Symbol string `json:"destination currency"`
}
func main() {
jsonString := `
{
"base currency": "USD",
"destination currency": "CNY"
}`
var rates Rates
err := json.Unmarshal([]byte(jsonString), &rates)
if err == nil {fmt.Println(rates.Base)
fmt.Println(rates.Symbol)
} else {fmt.Println(err)
}
}
运行如下代码:
$ go run main.go
USD
CNY
非结构化数据的映射
后面几节展现了绝对简略的 JSON 字符串。然而,在事实世界中,您要操作的 JSON 字符串通常很大且非结构化。此外,您可能只须要从 JSON 字符串中检索特定值。
思考以下 JSON 字符串:
{
"success": true,
"timestamp": 1588779306,
"base": "USD",
"date": "2022-01-15",
"rates": {
"BNB": 0.00225,
"BTC": 0.000020,
"EUR": 0.879,
"GBP": 0.733,
"CNY": 6.36
}
}
如果咱们还想把美元解析为其余币种,不至于从新定义整个构造体,能够采取定义一个接口:
var result map[string] interface{}
下面的语句创立了一个 map 类型的变量 result,它的 key 是 string 类型,每个对应的 value 都是 interface{} 类型。这个空接口示意该值能够是任何类型:
为了解析这个 JSON 字符串,咱们应该应用 json.Unmarshal()
函数:
json.Unmarshal([]byte(jsonString), &result)
因为 result 的类型是接口,所有能够传入任何类型:
- 当解析 success 键的话能够应用
result["sucess"]
,解析为布尔型。 - 当解析
timestamp
时能够解析为数字类型 - 解析 rates 应用传入
rates
即可, 即rates := result["rates"]
,解析为 map 类型
整个代码如下:
package main
import (
"encoding/json"
"fmt"
)
type Rates struct {
Base string `json:"base currency"`
Symbol string `json:"destination currency"`
}
func main() {
jsonString := `
{
"success": true,
"timestamp": 1588779306,
"base": "USD",
"date": "2022-01-15",
"rates": {
"BNB": 0.00225,
"BTC": 0.000020,
"EUR": 0.879,
"GBP": 0.733,
"CNY": 6.36
}
}`
var result map[string]interface{}
err := json.Unmarshal([]byte(jsonString), &result)
if err == nil {fmt.Println(result["success"])
rates := result["rates"]
fmt.Println(rates)
} else {fmt.Println(err)
}
}
运行代码如下:
$ go run main.go
true
map[BNB:0.00225 BTC:2e-05 CNY:6.36 EUR:0.879 GBP:0.733]
总结
JSON 数据作为常见的数据格式,有着十分多的应用场景。本篇文章介绍了如何利用 Go 语言来解析 JSON 数据,如解析为构造体、数组、嵌入对象,解析自定义字段和解析非结构化数据。下一篇文章将介绍一下如果将 Go 语言的数据编码为 JSON 数据,敬请期待!