Golang系列教程--JSON解析
source link: https://jjmeg.github.io/posts/golang-json/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Golang系列教程--JSON解析
「 json 」
提供了 JSON 与 Go 变量之间的序列化与反序列化。
📜本文内容
JSON序列化
func Marshal(v interface{}) ([]byte, error)
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
func main() {
amy := person{
Name: "Amy",
Country: "China",
City: "Beijing",
}
data1, _ := json.Marshal(amy)
fmt.Println(string(data1))
data2, _ := json.MarshalIndent(amy, "", " ")
fmt.Println(string(data2))
}
使用 MarshalIndent() 可使数据输出的形式美观一些
{"name":"Amy","country":"China","city":"Beijing"}
{
"name": "Amy",
"country": "China",
"city": "Beijing"
}
tag及使用技巧
1. 省略空字段 omitempty
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city,omitempty"`
}
func main() {
amy := person{
Name: "Amy",
}
data, _ := json.MarshalIndent(amy, "", " ")
fmt.Println(string(data))
}
JSON内的 city 字段增加 omitempty 关键字,初始化对象时未对该字段赋值,在序列化后将不显示;country 字段未注明忽略空值,序列化赋了默认0值:
{
"name": "Amy",
"country": ""
}
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"-"`
}
func main() {
amy := person{
Name: "Amy",
Country: "China",
City: "Beijing",
}
data, _ := json.MarshalIndent(amy, "", " ")
fmt.Println(string(data))
}
即使字段已经初始化,序列化后的内容也不会包含此字段
{
"name": "Amy",
"country": "China"
}
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Age int `json:"age,string"`
}
func main() {
amy := person{
Name: "Amy",
Age: 25,
}
data, _ := json.MarshalIndent(amy,""," ")
fmt.Printf("%s\n\n", string(data))
}
结构体内的 Age 字段为整型,加上 string 将本字段的值转化为字符串类型:
{
"name": "Amy",
"age": "25"
}
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
func main() {
amy := person{
Name: "Amy",
Country: "China",
City: "Beijing",
}
data, _ := json.MarshalIndent(
struct {
person
Gender string `json:"gender"`
}{
person: amy,
Gender: "female",
},""," ")
fmt.Println(string(data))
}
在序列化时新建一个结构体即可:
{
"name": "Amy",
"country": "China",
"city": "Beijing",
"gender": "female"
}
5. 多结构体组合成
从4中得到启发,可将多个结构体的字段组合成一个JSON
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
type occupation struct {
Company string `json:"company"`
Position string `json:"position"`
}
func main() {
amy := person{
Name: "Amy",
Country: "China",
City: "Beijing",
}
job := occupation{
Company: "Google",
Position: "developer",
}
data, _ := json.MarshalIndent(
struct {
person
occupation
}{
person: amy,
occupation: job,
}, "", " ")
fmt.Println(string(data))
}
{
"name": "Amy",
"country": "China",
"city": "Beijing",
"company": "Google",
"position": "developer"
}
6. 对时间类型的序列化
Go对时间的序列化方式是格式化转化成字符串,并默认使用RFC3339标准 2006-01-02T15:04:05.999999999Z07:00 做格式化,时间对象转化为JSON默认使用 MarshalJSON() 方法
func (t Time) MarshalJSON() ([]byte, error) {
if y := t.Year(); y < 0 || y >= 10000 {
// RFC 3339 is clear that years are 4 digits exactly.
// See golang.org/issue/4556#c15 for more discussion.
return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
}
b := make([]byte, 0, len(RFC3339Nano)+2)
b = append(b, '"')
b = t.AppendFormat(b, RFC3339Nano)
b = append(b, '"')
return b, nil
}
Marshaler 接口定义了 MarshalJSON() 方法,Go中的时间 time.Time 实现了 Marshaler 接口:
type Marshaler interface {
MarshalJSON() ([]byte, error)
}
结合上述思路,我们可以自定义时间类型,实现 Marshaler 接口,达到自定义序列化的目的:
package main
import (
"encoding/json"
"fmt"
"time"
)
//自定义时间类型
type MyTime time.Time
// 实现Marshaler接口
func (mytime MyTime) MarshalJSON() ([]byte, error) {
n := time.Time(mytime).Format("2006-01-02 15:04")
t := "\"" + n + "\""
return []byte(t), nil
}
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
Birthday MyTime `json:"birthday"`
}
func main() {
amy := person{
Name: "Amy",
Country: "China",
City: "Beijing",
Birthday: MyTime(time.Now()),
}
data, _ := json.MarshalIndent(amy, "", " ")
fmt.Println(string(data))
}
本例将时间输出格式修改为 年-月-日 时:分
{
"name": "Amy",
"country": "China",
"city": "Beijing",
"birthday": "2019-09-05 18:42"
}
JSON反序列化
func Unmarshal(data []byte, v interface{}) error
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
func main() {
data := `{
"name": "Amy",
"country": "China",
"city":"Beijing"
}`
amy := person{}
err := json.Unmarshal([]byte(data), &amy)
if err == nil {
fmt.Printf("%s\n%s\n%s\n", amy.Name, amy.Country, amy.City)
}
}
反序列化完成字符串到对象的转化,当 Unmarshal() 方法返回错误不空表示反序列化失败
Amy
China
Beijing
JSON反序列化的常用技巧
拆分成多个结构体
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
type occupation struct {
Company string `json:"company"`
Position string `json:"position"`
}
func main() {
data := `{
"name": "Amy",
"country": "China",
"city":"Beijing",
"company":"Google",
"position":"developer"
}`
amy := person{}
job := occupation{}
err := json.Unmarshal([]byte(data),
&struct {
*person
*occupation
}{&amy, &job})
if err == nil {
fmt.Printf("%v\n%v\n", amy, job)
}
}
{Amy China Beijing}
{Google developer}
JSON与私有属性
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
country string `json:"country"`
}
func main() {
d := `{
"name": "Amy",
"country": "China"
}`
amy := Person{}
err := json.Unmarshal([]byte(d),&amy)
if err == nil {
fmt.Printf("%v\n", amy)
}
Sam := Person{
Name: "Sam",
country: "CN",
}
data,err := json.Marshal(Sam)
if err == nil {
fmt.Printf("%v\n", string(data))
}
}
Person
内的 country
是私有属性,JSON的序列化及反序列化都不会对私有属性转化。
{Amy}
{"name":"Sam"}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK