golang-json使用(json tag)

结构体的tag

tag是结构体的元信息,运行时通过反射机制读取。结构体的tag一般定义在相应字段的后面,格式为:

fieldName fieldType  `key1:"value1" key2:"value2"

同一个结构体字段可以设置多个键值对tag,不同的键值对之间使用空格分隔。

json tag

默认情况下序列化与反序列化使用的都是结构体的原生字段名,可以通过给结构体字段添加json tag来指定序列化后的字段名。
例如代码:

package main

import (
	"fmt"
	"encoding/json"
)

type Student struct {
	Name   string  `json:"name"`
	Age    int64
	Weight float64
	Height float64
}

func main() {

	s1 := Student{
		Name:   "jack",
		Age:    20,
		Weight: 71.5,
		Height: 172.5,

	}

	b, err := json.Marshal(s1)
	if err != nil {
		fmt.Printf("json.Marshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("s1: %s\n", b)

	var s2 Student
	err = json.Unmarshal(b, &s2)
	if err != nil {
		fmt.Printf("json.Unmarshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("s2: %#v\n", s2)
}

输出:

s1: {"name":"jack","Age":20,"Weight":71.5,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:71.5, Height:172.5}

使用json tag序列化时忽略任一字段

使用“-”作为相应字段json tag的value值,如:

type Student struct {
	Name   string  `json:"name"`
	Age    int64
	Weight float64  `json:"-"`
	Height float64
}

输出:

s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}

注:反序列化时仍将恢复该字段,零值处理。

使用json tag序列化时忽略普通结构体中的为空字段

使用“omitempty”作为相应字段json tag的value值,注意此时在“omitempty”前一定指定一个字段名,否则“omitempty”将作为字段名处理。如:

type Student struct {
	Name   string  `json:"name"`
	Age    int64
	Weight float64  `json:"weight,omitempty"`
	Height float64
}

此时如果这样初始化s1:

    s1 := Student{
		Name:   "jack",
		Age:    20,
		Height: 172.5,
	}

输出:

s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}

可见,空字段Weight在序列化时被忽略掉了。
如果这样初始化s1:

    s1 := Student{
		Name:   "jack",
		Age:    20,
		Weight: 0,
		Height: 172.5,
	}

输出:

s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}

可见,使用“omitempty”的字段为零值时在序列化结果中也被忽略掉了。

使用json tag 忽略嵌套结构体中的为空字段

由于具名嵌套结构体与匿名嵌套结构体在序列化后只存在是否摊平的区别,这里不做细致讨论,使用匿名嵌套结构体(这里注:若使用匿名嵌套结构体,但同时使用json tag为该被嵌套结构体指定了字段名,序列化结果该被嵌套结构体不会被摊平)。
若要在被嵌套结构体中的某一字段为空时使其在序列化结果中被忽略,操作方法与上方普通结构体中字段一致。
若要在被嵌套结构体整体为空时使其在序列化结果中被忽略,不仅要在被嵌套结构体字段后加上json:"fileName,omitempty",还要将其改为结构体指针。如:

type BodyInfo struct {
	Weight float64    
	Height float64
}

type Student struct {
	Name   string  `json:"name"`
	Age    int64
    *BodyInfo       `json:"bodyinfo,omitempty"`
}

此时s1为:

    s1 := Student{
		Name:   "jack",
		Age:    20,
	}

输出:

s1: {"name":"jack","Age":20}
s2: main.Student{Name:"jack", Age:20, BodyInfo:(*main.BodyInfo)(nil)}

不修改原结构体忽略某字段

需要创建另外一个结构体来匿名嵌套原结构体,同时指定待忽略字段为匿名结构体指针类型,并添加omitempty的json tag。如:

package main

import (
	"fmt"
	"encoding/json"
)

type Student struct {
	Name   string  `json:"name"`
	Age    int64   `json:"age"`
	Weight float64
	Height float64
}

type PStudent struct {
	*Student
	Age *struct{}   `json:"age,omitempty"`
}

func main() {

	s1 := Student{
		Name:   "jack",
		Age:    20,
		Weight: 61.5,
		Height: 172.5,
	}

	ps1 := PStudent{
		Student: &s1,
	}

	b, err := json.Marshal(ps1)
	if err != nil {
		fmt.Printf("json.Marshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("s1: %s\n", b)

	var s2 PStudent
	err = json.Unmarshal(b, &s2)
	if err != nil {
		fmt.Printf("json.Unmarshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("s2.student: %#v s2.age: %v\n", *s2.Student, s2.Age)
}

输出:

s1: {"name":"jack","Weight":61.5,"Height":172.5}
s2.student: main.Student{Name:"jack", Age:0, Weight:61.5, Height:172.5} s2.age: <nil>

猜你喜欢

转载自blog.csdn.net/somanlee/article/details/106925278
tag
今日推荐