GoLang中Json Tag用法实例总结

目录
  • 前言
  • Json中Tag用法汇总
  • 官方 Marshal 函数说明
  • 参考
  • 总结

前言

GoLang中结构体的 JSON Tag 标识(英文名backquote或backtick,反引号 ` 符号包裹的部分内容)一直未明确看过完整规范和使用说明,存在模棱两可,系统整理如下:

  • JSON Tag标签的完整语法,包含哪些选项
  • 不同选项(输出名/-/omitempty/string)的作用及使用范围
  • 特殊注意事项补充

Json中Tag用法汇总

  • JSON Tag标签格式为:json:"FieldName/-/可选,omitempty/可选,string/可选
  • 多个选项之间使用 , 逗号分割
  • FieldName选项:指定编码后键名称
    • 可为空,则使用Struct对应字段名作为JSON输出名
    • FieldName非空,则使用指定的FieldName作为JSON输出名
    • -符号,输出时忽略此字段;但要注意-,(多一个逗号结尾)时,输出字段名为-的JSON字段,而不是忽略
  • omitempty选项:忽略空值
    • 包含此选项,输出时字段空值(零值+空值:false、0、nil指针、nil接口值,以及任何空数组、切片、map或字符串)则不输出
  • string选项:结果输出为字符串
    • 字段结果输出为字符串
    • 只适用于字符串、浮点、整数或布尔类型的字段
    • 这种额外的编码有时在与 JavaScript 程序通信时使用
    • 要注意,如果字段值本身为string时,再次增加JSON的string标签选项,会导致多个引号的情况
// 示例代码:https://go.dev/play/p/ApzFQttV_MB
package main

import (
    "encoding/json"
    "fmt"
    "os"
)

func main() {
    type ColorGroup struct {
        Hello   bool     `json:"Hello,string"`
        world   bool     `json:"World,string"`
        ID      int      `json:"id,string"`
        Name    string   `json:"name,string"`
        Colors  []string `json:"ColorName,omitempty"`
        Colors1 []string `json:"ColorName1"`
        Colors2 []string `json:"ColorName2"`
    }
    group := ColorGroup{
        Hello:   true,
        world:   true,
        ID:      1,
        Name:    "Reds",
        Colors:  []string{"hello", "world"},
        Colors1: nil,
        Colors2: []string{},
    }
    b, err := json.Marshal(group)
    if err != nil {
        fmt.Println("error:", err)
    }
    os.Stdout.Write(b)
}

// 输出结果
//{"Hello":"true","id":"1","name":"\"Reds\"","ColorName":["hello","world"],"ColorName1":null,"ColorName2":[]}

其他注意:

  • nil 指针、nil 接口、nil切片等nil类型值,进行编码后为 null JSON 对象
  • 空切片、空数组编码为 [] JSON 数组
  • map 编码为 {} JSON 对象
  • 指针类型值编码为指针所指向的值,接口类型值编码后为对应类型的值

官方 Marshal 函数说明

func Marshal(v interface{}) ([]byte, error)

Marshal 返回变量 v 的 JSON 编码后结果

Marshal 函数会递归的处理变量 v;如果一个值实现了Marshaler接口,并且不是一个nil指针,Marshal 调用其 MarshalJSON 方法来生成 JSON 数据。如果没有 MarshalJSON 方法但实现了 encoding.TextMarshaler 方法,Marshal 调用 MarshalText 方法并将结果编码为 JSON 字符串。nil 指针异常并不是严格意义上的必须,而是模仿了UnmarshalJSON行为中的一个类似的、必须的异常。

否则,Marshal使用以下与类型有关的默认编码:

  • 布尔值被编码为JSON布尔值
  • 浮点、整数和数值类型值编码为JSON数字
  • 字符串值被编码为JSON字符串,被强制为有效的UTF-8,用Unicode替换符文替换无效的字节。为了使JSON能够安全地嵌入到HTML <script>标签中,字符串使用HTMLEscape进行编码,将”<”、”>”、”&”、”U+2028”和”U+2029”转义为”\u003c”、”\u003e”、”\u0026”、”\u2028”、和”\u2029”。在使用编码器时,可以通过调用SetEscapeHTML(false)禁用这种替换。
  • 数组和分片的值会被编码为JSON数组,但[]byte会被编码为base64编码的字符串,而nil切片会被编码为null JSON对象值。
    • 数组、分片,编码后为 JSON 数组
    • []byte空切片,编码后为空数组 []
    • nil 切片,编码后为 null
  • 结构体类型的值被编码为JSON对象。每个导出的结构字段都会成为对象的成员,使用字段名作为对象的键,除非字段因为下面的原因被省略
    • 每个结构字段的编码都可通过存储在结构字段Tag标签的 “json” 键下的格式字符串来定制。格式字符串给出了字段的名称,后面可能有一个用逗号分隔的选项列表。名称可以是空的,以便指定选项而不覆盖默认的字段名
    • “omitempty”选项,如果字段为空值,应该从编码中省略,定义为false、0、nil指针、nil接口值,以及任何空数组、切片、map或字符串
    • 作为一种特殊情况,如果字段标签是”-“,字段总是被省略的。请注意,一个名称为”-“的字段仍然可以使用标签”-,”来生成

结构体字段Tag标签下 json 键对应格式化字符串说明:

  • 给出字段编码后的名称,后面可能有一组逗号分割的选项列表
  • 字段名称可以为空,用于在不覆盖默认字段名的情况下指定不同选项
  • omitempty选项,字段为空值(false/0/nil指针/nil接口值/空数组/空切片/空map/空字符串)时则跳过编码输出
  • 字段标签为-时,此字段总是被忽略;但要注意,名为-的字段出现在-,标签中时仍可以被生成

结构体字段标签和对应含义的一些例子:

// Field appears in JSON as key "myName".
// 该字段出现在JSON中时,名为"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.
// 该字段出现在JSON中时,名为"myName",如为零值则输出时忽略此字段
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.
// 该字段出现在JSON中时,名为"Field",如为零值则输出时忽略此字段
Field int `json:",omitempty"`

// Field is ignored by this package.
// 该字段当前包输出JSON时忽略
Field int `json:"-"`

// Field appears in JSON as key "-".
// 该字段出现在JSON中时,名为"-"
Field int `json:"-,"`

"string" 选项表示字段以 JSON 格式存储在 JSON 编码的字符串中。它只适用于字符串、浮点、整数或布尔类型的字段。这种额外的编码有时在与JavaScript程序通信时使用。

Int64String int64 `json:",string"`

键名满足以下条件时将被使用:非空字符串,仅由Unicode字母、数字和ASCII标点符号(不包括引号、反斜杠和逗号)组成。

受下文所述的Go可见性规则的限制,匿名结构字段通常可被编码,其内部可导出的字段等价于外部结构中的字段。匿名结构体字段使用其JSON Tag标签中给出名称,而不是匿名的。接口类型的匿名结构字段的处理方式与将该类型作为其名称相同,也不是匿名。

在决定对哪个字段进行marshal或unmarshal时,Go中结构体字段可见性规则进行了调整。如果在同一级别有多个字段,并且该级别是嵌套最少的(且将是通常Go规则所选择的嵌套级别),则适用以下额外规则:

1) 在这些字段中,如果有任何字段是JSON Tag标记的,就只考虑有标记的字段,即使有多个未标记的字段,否则会发生冲突。

2) 如果只有一个字段(根据第一条规则标记或不标记),该字段被选中。

3) 否则有多个字段,都会被忽略;不会发生错误。

Go 1.1中新增了对匿名结构字段的处理。在Go 1.1之前,匿名结构字段被忽略。要在当前版本和早期版本中强制忽略匿名结构字段,请给该字段一个”-“的JSON标签。

Map的值被编码为JSON对象。地图的键类型必须是字符串、整数类型,或者实现了encoding.TextMarshaler接口。通过应用以下规则对Map的键进行排序并作为JSON对象的键使用,但要遵守上面为字符串值描述的UTF-8强制规则。

- 任何字符串类型的键都可以直接使用
- encoding.TextMarshalers 将被编码
- 整数键被转换为字符串

指针类型值被编码为所指向的值,一个 nil 指针会被编码为 null JSON值。

接口类型值编码为接口中包含的值,一个 nil 接口值被编码为 null JSON值。

通道(Channel)、复合类型(complex)和函数值(function)不能进行JSON编码,试图对这样的值进行编码会导致Marshal返回一个UnsupportedTypeError错误。
JSON不能代表循环嵌套的数据结构,Marshal函数也将不处理它们。向Marshal传递循环结构将导致一个错误。

参考

总结

到此这篇关于GoLang中Json Tag用法的文章就介绍到这了,更多相关GoLang中Json Tag用法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • GoLang中Json Tag用法实例总结

    目录 前言 Json中Tag用法汇总 官方 Marshal 函数说明 参考 总结 前言 GoLang中结构体的 JSON Tag 标识(英文名backquote或backtick,反引号 ` 符号包裹的部分内容)一直未明确看过完整规范和使用说明,存在模棱两可,系统整理如下: JSON Tag标签的完整语法,包含哪些选项 不同选项(输出名/-/omitempty/string)的作用及使用范围 特殊注意事项补充 Json中Tag用法汇总 JSON Tag标签格式为:json:"FieldName/

  • golang struct json tag的使用以及深入讲解

    目录 一.sturct json tag的使用 1.tag格式说明 2.具体使用格式说明 二.源码角度的设计处理过程 1.typeFields 2.encode 三.总结 一.sturct json tag的使用 1.tag格式说明 struct json tag主要在struct与json数据转换的过程(Marshal/Unmarshal)中使用. json的tag格式如下: Key type  `json:"name,opt1,opt2,opts..."` 说明: 变量必须是可导出

  • Golang 中反射的应用实例详解

    目录 引言 Golang类型设计原则 Golang 中为什么要使用反射/什么场景可以(应该)使用反射 举例场景: 反射的基本用法 反射的性能分析与优缺点 测试反射结构体初始化 测试结构体字段读取/赋值 测试结构体方法调用 优缺点 反射在 okr 中的简单应用 结论 引言 首先来一段简单的代码逻辑热身,下面的代码大家觉得应该会打印什么呢? type OKR struct { id int content string } func getOkrDetail(ctx context.Context,

  • golang中json操作的完全指南

    目录 前言 1. 结构体与JSON互转 2. map与JSON互转 3. 结构体的变量不加tag标签能否正常转成json数据 4. JSON操作的一些小技巧 (1)忽略掉 struct 指定字段 (2)添加额外的字段 (3)合并两个 struct (4)字符串传递给 int类型 (5)一个 json 分成两个struct 补充:GoLang json格式化输出 总结 前言 JSON是一种轻量级的数据交换格式.易于阅读和编写. golang 提供了 encoding/json 包来操作JSON数据

  • MySQL数据类型中DECIMAL的用法实例详解

    MySQL数据类型中DECIMAL的用法实例详解 在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都有各自的作用,下面我们就主要来介绍一下MySQL数据类型中的DECIMAL类型的作用和用法. 一般赋予浮点列的值被四舍五入到这个列所指定的十进制数.如果在一个FLOAT(8, 1)的列中存储1. 2 3 4 5 6,则结果为1. 2.如果将相同的值存入FLOAT(8, 4) 的列中,则结果为1. 2 3 4 6. 这表示应该定义具有足够位数的浮点列以便

  • 基于多线程中join()的用法实例讲解

    Thread中,join()方法的作用是调用线程等待该线程完成后,才能继续用下运行. public class TestThread5 { public static void main(String[] args) throws InterruptedException { Runner0 run5 = new Runner0(); Thread th5 = new Thread(run5); th5.start(); th5.join();//join()方法用在此处是为了等待主线程结束后运

  • 详解Golang中Channel的用法

    如果说goroutine是Go语言程序的并发体的话,那么channels则是它们之间的通信机制.一个channel是一个通信机制,它可以让一个goroutine通过它给另一个goroutine发送值信息. 1 创建channel 每个channel都有一个特殊的类型,也就是channels可发送数据的类型.一个可以发送int类型数据 的channel一般写为chan int.使用内置的make函数,如果第二个参数大于0,则表示创建一个带缓存的channel. ch := make(chan in

  • Golang中Json的序列化和反序列化的使用

    目录 JSON: 创建格式: 基本数据类型序列化: map序列化: 切片序列化: 反序列化为结构体: 反序列化为map: 反序列化为切片: JSON: JSON(JavaScript Object Notation):是一种轻量级的数据交换格式. 它是基于 ECMAScript 规范的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据. 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言.易于人阅读和编写,同时也易于计算机解析和生成,并有效的 提升网络传输效率. Json易于机器

  • SeaJS中use函数用法实例分析

    本文实例讲述了SeaJS中use函数用法.分享给大家供大家参考,具体如下: 有了 define 等模块定义规范的实现,我们可以开发出很多模块.但光有一堆模块不管用,我们还得让它们能跑起来.在 SeaJS 里,要启动模块系统很简单: <script src="path/to/sea.js"></script> <script> seajs.use('./main'); </script> seajs.use 用来在页面中加载模块.通过 us

  • python中urllib模块用法实例详解

    本文实例讲述了python中urllib模块用法.分享给大家供大家参考.具体分析如下: 一.问题: 近期公司项目的需求是根据客户提供的api,我们定时去获取数据, 之前的方案是用php收集任务存入到redis队列,然后在linux下做一个常驻进程跑某一个php文件, 该php文件就一个无限循环,判断redis队列,有就执行,没有就break. 二.解决方法: 最近刚好学了一下python, python的urllib模块或许比php的curl更快,而且简单. 贴一下代码 复制代码 代码如下: #

随机推荐