一、介绍

1.tag格式说明

struct json tag主要在struct与json数据转换的过程(Marshal/Unmarshal)中使用。

Key type  `json:"name,opt1,opt2,opts..."`

需要解析的字段,Key,第一个字母需要大写。
tag之间通过","分割,第一个是name,可以不写。
源码src/encoding/json/tags.go

func parseTag(tag string) (string, tagOptions) {
    if idx := strings.Index(tag, ","); idx != -1 {
        return tag[:idx], tagOptions(tag[idx+1:])
    }
    return tag, tagOptions("")
}

2.tag格式三种情况

json后面可以跟的tag有三种情况

1. "-"
2. "string"
3. "omitempty"

在源码src/encoding/json/encode.go

func typeFields(t reflect.Type) structFields{
//.........省略
tag := sf.Tag.Get("json")
//当tag为 "-"的时候,此字段不生成json
if tag == "-" {
    continue
}
//.........省略
//当tag里面有"string"字段的时候,把原来的类型,转成string
// Only strings, floats, integers, and booleans can be quoted.
quoted := false
if opts.Contains("string") {
    switch ft.Kind() {
        case reflect.Bool,reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
                        reflect.Float32, reflect.Float64,
                        reflect.String:
                        quoted = true
                    }
                }
}
//.........省略
//处理tag里面包含 "omitempty"
field := field{
    name:      name,
    tag:       tagged,
    index:     index,
    typ:       ft,
    omitEmpty: opts.Contains("omitempty"),
    quoted:    quoted,
}

二、使用举例

2.1 不指定tag

不指定的话,和字段同名如下:

Field string // "Filed":""

举例:

import (
    "encoding/json"
    "testing"
)

type User struct {
    Name string //不指定tag
}

func TestTag(t *testing.T) {
    var user = User{Name: "hisheng"}
    s, err := json.Marshal(user)
    t.Log(string(s), err)
}

输出:

{"Name":"hisheng"} <nil>

2.2 直接忽略

Field int json:"-" //注意:必须为"-",不能带有其他tags

举例:

import (
    "encoding/json"
    "testing"
)

type User struct {
    Name string `json:"-"`
}

func TestTag2(t *testing.T) {
    var user = User{Name: "hisheng"}
    s, err := json.Marshal(user)
    t.Log(string(s), err)
}

输出:

{} <nil>

2.3 指定key名

Field int json:"field" 

指定key名,在生成的json后,就是指定的那个key名
举例:

import (
    "encoding/json"
    "testing"
)

type User struct {
    Name string `json:"name"`
}

func TestTag2(t *testing.T) {
    var user = User{Name: "hisheng"}
    s, err := json.Marshal(user)
    t.Log(string(s), err)
}

输出:

{"name":"hisheng"} <nil>

2.4 "omitempty"零值忽略

加了omitempty的,只要是此字段的默认零值,就不
注意,omitempty需要放在第二个,第一个tag是字段的key

Field string json:",omitempty" 

举例:
import (

"encoding/json"
"testing"

)

type User struct {

Name string `json:"name,omitempty"`

}

func TestTag2(t *testing.T) {

var user = User{Name: ""}
s, err := json.Marshal(user)
t.Log(string(s), err)

}
输出:

{} <nil>

2.5 "string"转字符串

"string"仅适用于字符串、浮点、整数或布尔类型,表示的意思是:将字段的值转换为字符串;解析时,则是将字符串解析为指定的类型。

import (
    "encoding/json"
    "testing"
)

type User struct {
    Age int `json:"age,string"`
}

func TestTag3(t *testing.T) {
    var user = User{Age: 10}
    s, err := json.Marshal(user)
    t.Log(string(s), err)
}

输出:

{"age":"10"} <nil>

谢谢您的观看,欢迎关注我的公众号。

image.png


海生
104 声望32 粉丝

与黑夜里,追求那一抹萤火。