将一个Go语言中结构体slice转为JSON的过程叫编组(marshaling),通过调用json.Marshal函数完成编码,编码的逆操作是解码,对应将JSON数据解码为Go语言的数据结构,Go语言中一般叫unmarshaling,通过调用 json.Unmarshaling函数完成解码;
package main
import (
"encoding/json"
"fmt"
"time"
)
type Article struct {
ID uint
Title string
Filename string `json:"filename,omitempty"`
AuthorId uint `json:"authorId"`
CreatedAt time.Time
UpdatedAt time.Time
}
func main() {
var articles = []Article{
{Title: "文章标题1", Filename: "article.text", AuthorId: 123},
{Title: "文章标题1", AuthorId: 123},
}
data, _ := json.Marshal(articles)
fmt.Printf("%s\n", data)
}
输入出结果如下:
[{"ID":0,"Title":"文章标题1","filename":"article.text","authorId":123},{"ID":0,"Title":"文章标题1","authorId":123}]
这种紧凑的表示形式虽然包含了全部的信息,但是很难阅读。为了生成便于阅读的格式,使用 json.MarshalIndent
函数将产生整齐缩进的输出。该函数有两个额外的字符串参数用于表示每一行输出 的前缀和每一个层级的缩进:
//data, _ := json.Marshal(articles)
data, _ := json.MarshalIndent(articles, "", " ")
替换后输出结果如下:
[
{
"ID": 0,
"Title": "文章标题1",
"filename": "article.text",
"authorId": 123
},
{
"ID": 0,
"Title": "文章标题1",
"authorId": 123
}
]
在Article
结构体声明中,Filename
和AuthorId
成员后面的字符串面值是结构体成员Tag;结构体的成员Tag可以是任意的字符串面值,但是通常是一系列用空格分隔的key:"value"键值对序列; 因为值中含义双引号字符,因此成员Tag一般用原生字符串面值的形式书写;
成员Tag中json开头键名对应的值用于控制encoding/json包的编码和解码的行为,并且encoding/...下面其它的包也遵循这个约定。成员Tag 中json对应值的第一部分用于指定JSON对象的名字,如上:Filename
和AuthorId
字段Tag中第一部分指定了JSON对象的名字;Tag还带了一个额外的omitempty
选项,表示当Go语言结构体成员为空或 零值时不生成JSON对象
下面的代码将JSON格式的数据解码为一个结构体
var articles2 []Article
var err error
err = json.Unmarshal(data, &articles2)
fmt.Println(articles2) // [{0 文章标题1 article.text 123} {0 文章标题1 123}]
json.Unmarshal
接收两个参数,分别是[]byte
字节slice 和 interface{}
类型,并返回 errort类型的值;