kevinyan815/gocookbook

用JSON编码数据

kevinyan815 opened this issue · 0 comments

要格式化成JSON的数据需要先存储到结构体变量中

type Address struct {
    Type    string
    City    string
    Country string
}

type CreditCard struct {
    FirstName string
    LastName  string
    Addresses []*Address
    Remark    string
}

home := &Address{"private", "Aartselaar", "Belgium"}
office := &Address{"work", "Boom", "Belgium"}
card := VCard{"Jan", "Kersschot", []*Address{home, office}, "none"}

使用json包中的json.Marshal()对数据进行JOSN格式化,返回一个编码后的JOSN文本,其类型是字节切片[]byte

在编码时,默认使用Go语言结构体的成员名字作为JSON的对象名(在结构体声明的成员tag里可以自定义 JSON 对象名)。只有导出的结构体成员才会被编码,这也就是我们为什么选择用大写字母开头的成员名称。

js, err := json.Marshal(card)
fmt.Printf("JSON format: %s", js)

出于安全考虑,在 web 应用中最好使用 json.MarshalforHTML() 函数,其对数据执行 HTML 转码,所以文本可以被安全地嵌在 HTML <script> 标签中。

为什么空slice会在JSON里被格式化为null

slice的零值为nil无指向内存的地址,所以当以var f []int初始化slice后,在 JSON中将其编码为null,如果想在 JSON 中将空 slice 编码为[]则需用make初始化 slice为其分配内存地址:

下面的例子可以看出两点的区别

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Friends []string
}

func main() {
	var f1 []string
	f2 := make([]string, 0)

	json1, _ := json.Marshal(Person{f1})
	json2, _ := json.Marshal(Person{f2})

	fmt.Printf("%s\n", json1)
	fmt.Printf("%s\n", json2)
}

可以控制JSON 编码行为的一些结构体字段注解

// Field is ignored by this package.
Field int `json:"-"`

// Field appears in JSON as key "myName".
Field int `json:"myName"`

// Field appears in JSON as key "myName" and
// the field is omitted from the object if its value is empty,
// as defined above.
Field int `json:"myName,omitempty"`

// Field appears in JSON as key "Field" (the default), but
// the field is skipped if empty.
// Note the leading comma.
Field int `json:",omitempty"`