在现代程序中,在两个程序之间进行通信非常重要。无论是一个[Go]程序检查用户是否有权限访问另一个程序,一个[JavaScript]程序获取过去的订单列表以在网站上显示,还是一个Rust程序从文件中读取测试结果,程序都需要一种方法为其他程序提供数据。然而,许多编程语言都有自己的内部存储数据的方式,这是其他语言所不理解的。为了允许这些语言进行交互,需要将数据转换为一种它们都能理解的通用格式。其中,[JSON]是在互联网上传输数据以及在同一系统中的程序之间传输数据的一种流行方式。
许多现代编程语言在其标准库中都包含了一种将数据与JSON进行转换的方法,Go也是如此。通过使用Go提供的encoding/json
包,您的Go程序也将能够与任何其他可以使用json通信的系统进行交互。
在本教程中,您将从创建一个程序开始,该程序使用encoding/json
包将map
中的数据编码为json数据,然后更新您的程序,使用struct
类型来编码数据。之后,你将更新你的程序,在最终将JSON数据解码为struct
类型之前,将JSON数据解码为map
类型。
Go对JSON编码和解码的支持是由标准库的encoding/json
包提供的。您将使用该包中的第一个函数是json.Marshal
函数。编组,有时也称为序列化,是将内存中的程序数据转换为可以在其他地方传输或保存的格式的过程。json.Marshal
函数用于将Go数据转换为JSON数据。json.Marshal
函数接受一个interface{}
类型的值作为将其封送为JSON的值,因此任何值都可以作为参数传入,并将返回JSON数据作为结果。在本节中,您将使用json.Marshal
函数创建一个程序,以从Go map
值生成包含各种类型数据的JSON,然后将这些值打印到输出。
大多数JSON都表示为一个对象,键为string
,值为各种其他类型。因此,在Go中生成JSON数据的最灵活方法是使用string
键和interface{}
值将数据放入map
中。string
键可以直接转换为JSON对象键,并且interface{}
值允许该值为任何其他值,无论是string
、int
,甚至是另一个map[string]interface{}
。
要在程序中使用encoding/json
包,你需要为程序创建一个目录。在本教程中,你将使用一个名为projects
的目录。
首先,创建projects
目录并导航到它:
mkdir projects
cd projects
接下来,创建项目目录。在这种情况下,使用目录jsondata
:
mkdir jsondata
cd jsondata
在jsondata
目录下,使用nano
或者你喜欢的编辑器来打开main.go
文件:
nano main.go
在main.go
文件中,你将添加一个main
函数来运行你的程序。接下来,你将添加一个包含各种键和数据类型的map[string]interface{}
值。然后,你将使用json.Marshal
函数将map
数据封送为JSON数据。
在main.go
中添加以下代码:
main.go
package main
import (
"encoding/json"
"fmt"
)
func main() {
data := map[string]interface{
}{
"intValue": 1234,
"boolValue": true,
"stringValue": "hello!",
"objectValue": map[string]interface{
}{
"arrayValue": []int{
1, 2, 3, 4},
},
}
jsonData, err := json.Marshal(data)
if err != nil {
fmt.Printf("could not marshal json: %s\n", err)
return
}
fmt.Printf("json data: %s\n", jsonData)
}
你会在data
变量中看到,每个值都有一个string
作为键,但这些键的值是不同的。一个是int
类型的值,另一个是bool
类型的值,甚至还有一个是内部带有[]int
类型的map[string]interface{}
类型的值。
当你将data
变量传递给json.Marshal
时,该函数将遍历你提供的所有值,并确定它们的类型以及如何在JSON中表示它们。如果翻译过程中有任何问题,json.Marshal
函数将返回一个描述问题的error
。如果转换成功,jsonData
变量将包含编组的JSON数据的[]字节
。由于可以使用myString:= string(jsonData)
或格式字符串中的%s
动词将[]字节
值转换为string
值,然后可以使用fmt.Printf
将JSON数据打印到屏幕上。
保存并关闭文件。
要查看程序的输出,使用go run
命令并提供main.go
文件:
go run main.go
Outputjson data: {
"boolValue":true,"intValue":1234,"objectValue":{
"arrayValue":[1,2,3,4]},"stringValue":"hello!"}
在输出中,你会看到顶层的JSON值是一个用大括号({}
)括起来的对象。你包含在data
中的所有值都存在。你还会看到objectValue
的map[string]interface{}
被转换为另一个由{}
包围的JSON对象,并且在其中还包含arrayValue
,其数组值为[1,2,3,4]
。
encoding/json
包不仅支持string
和int
类型的值。它还可以编码更复杂的类型。它支持的更复杂的类型之一是time
包中的time.Time
类型。
**注意:**有关Go的time
包的更多信息,请查看教程,如何在Go中使用日期和时间
为了看看实际效果,再次打开你的main.go
文件,并使用time.Date
函数在你的数据中添加一个time.Time
值:
main.go
package main
import (
"encoding/json"
"fmt"
"time"
)
func main() {
data := map[string]interface{
}{
"intValue": 1234,
"boolValue": true,
"stringValue": "hello!",
"dateValue": time.Date(2022, 3, 2, 9, 10, 0, 0