自定义属性名称的映射
有时 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 数据,如解析为结构体、数组、嵌入对象,解析自定义字段和解析非结构化数据。