详解Go中JSON处理

Go语言内建对JSON的支持。使用Go语言内置的encoding/json标准库,开发者可以轻松使用Go程序生成和解析JSON格式的数据。在Go语言实现JSON的编码和解码时,遵循RFC4627协议标准。

基本的序列化

首先我们来看一下Go语言中json.Marshal()(系列化)与json.Unmarshal(反序列化)的基本用法。

type Person struct {
Name  string
Age  int64
Weight float64
}

func main() {
p1 := Person{
Name:  "小明",
Age:  18,
Weight: 71.5,
}
// struct -> json string
b, err := json.Marshal(p1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b)
// json string -> struct
var p2 Person
err = json.Unmarshal(b, &p2)
if err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("p2:%#v\n", p2)
}

输出: str:{“Name”:”小明”,”Age”:18,”Weight”:71.5} p2:main.Person{Name:”小明”, Age:18, Weight:71.5}

结构体tag介绍

Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来。 Tag在结构体字段的后方定义,由一对反引号包裹起来,具体的格式如下:

`key1:"value1" key2:"value2"`

结构体tag由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。 同一个结构体字段可以设置多个键值对tag,不同的键值对之间使用空格分隔。

使用json tag指定字段名

序列化与反序列化默认情况下使用结构体的字段名,我们可以通过给结构体字段添加tag来指定json序列化生成的字段名。

// 使用json tag指定序列化与反序列化时的行为
type Person struct {
Name  string `json:"name"` // 指定json序列化/反序列化时使用小写name
Age  int64
Weight float64
}

忽略某个字段

如果你想在json序列化/反序列化的时候忽略掉结构体中的某个字段,可以按如下方式在tag中添加-。

// 使用json tag指定json序列化与反序列化时的行为
type Person struct {
Name  string `json:"name"` // 指定json序列化/反序列化时使用小写name
Age  int64
Weight float64 `json:"-"` // 指定json序列化/反序列化时忽略此字段
}

忽略空值字段

当 struct 中的字段没有值时, json.Marshal() 序列化的时候不会忽略这些字段,而是默认输出字段的类型零值(例如int和float类型零值是 0,string类型零值是””,对象类型零值是 nil)。如果想要在序列序列化时忽略这些没有值的字段时,可以在对应字段添加omitempty tag。 举个例子:

type User struct {
Name string  `json:"name"`
Email string  `json:"email"`
Hobby []string `json:"hobby"`
}

func omitemptyDemo() {
u1 := User{
Name: "小明",
}
// struct -> json string
b, err := json.Marshal(u1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b)
}

输出结果: str:{“name”:”小明”,”email”:””,”hobby”:null}

如果想要在最终的序列化结果中去掉空值字段,可以像下面这样定义结构体:

// 在tag中添加omitempty忽略空值
// 注意这里 hobby,omitempty 合起来是json tag值,中间用英文逗号分隔
type User struct {
Name string  `json:"name"`
Email string  `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
}

此时,再执行上述的omitemptyDemo,输出结果如下: str:{“name”:”小明”} // 序列化结果中没有email和hobby字段

说句题外话,我们使用gorm操作数据库的话,经常会遇到想忽略指定字段修改的问题,比如结构体中的关联实体,只想json展示,form提交时忽略实体,这种问题我会单独整理一篇出来。

忽略嵌套结构体空值字段

首先来看几种结构体嵌套的示例:

type User struct {
Name string  `json:"name"`
Email string  `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
Profile
}

type Profile struct {
Website string `json:"site"`
Slogan string `json:"slogan"`
}

func nestedStructDemo() {
u1 := User{
Name: "小明",
Hobby: []string{"足球""篮球"},
}
b, err := json.Marshal(u1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b)
}

匿名嵌套Profile时序列化后的json串为单层的: str:{“name”:”小明”,”hobby”:[“足球”,”蓝球”],”site”:””,”slogan”:””}

想要变成嵌套的json串,需要改为具名嵌套或定义字段tag:

type User struct {
Name  string  `json:"name"`
Email  string  `json:"email,omitempty"`
Hobby  []string `json:"hobby,omitempty"`
Profile `json:"profile"`
}
// str:{"name":"小明","hobby":["足球","篮球"],"profile":{"site":"","slogan":""}}

想要在嵌套的结构体为空值时,忽略该字段,仅添加omitempty是不够的:

type User struct {
Name   string  `json:"name"`
Email  string  `json:"email,omitempty"`
Hobby  []string `json:"hobby,omitempty"`
Profile `json:"profile,omitempty"`
}
// str:{"name":"小明","hobby":["足球","篮球"],"profile":{"site":"","slogan":""}}

还需要使用嵌套的结构体指针:

type User struct {
Name   string  `json:"name"`
Email  string  `json:"email,omitempty"`
Hobby  []string `json:"hobby,omitempty"`
*Profile `json:"profile,omitempty"` //这里是重点
}
// str:{"name":"小明","hobby":["足球","篮球"]}

不修改原结构体忽略空值字段

我们需要json序列化User,但是不想把密码也序列化,又不想修改User结构体,这个时候我们就可以使用创建另外一个结构体PublicUser匿名嵌套原User,同时指定Password字段为匿名结构体指针类型,并添加omitemptytag,示例代码如下:

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

type PublicUser struct {
*User       // 匿名嵌套
Password *struct{} `json:"password,omitempty"`
}

func omitPasswordDemo() {
u1 := User{
Name:   "小明",
Password: "123456",
}
b, err := json.Marshal(PublicUser{User: &u1})
if err != nil {
fmt.Printf("json.Marshal u1 failed, err:%v\n", err)
return
}
fmt.Printf("str:%s\n", b) // str:{"name":"小明"}
}

优雅处理字符串格式的数字

有时候,前端在传递来的json数据中可能会使用字符串类型的数字,这个时候可以在结构体tag中添加string来告诉json包从字符串中解析相应字段的数据:

type Card struct {
ID  int64  `json:"id,string"`  // 添加string tag
Score float64 `json:"score,string"` // 添加string tag
}

func intAndStringDemo() {
jsonStr1 := `{"id""1234567","score""88.50"}`
var c1 Card
if err := json.Unmarshal([]byte(jsonStr1), &c1); err != nil {
fmt.Printf("json.Unmarsha jsonStr1 failed, err:%v\n", err)
return
}
fmt.Printf("c1:%#v\n", c1) // c1:main.Card{ID:1234567, Score:88.5}
}

原创文章,作者:晴川运维,如若转载,请注明出处:https://baike.qcidc.com/6758.html

(0)
晴川运维晴川运维
上一篇 2025年6月8日
下一篇 2025年6月8日

相关推荐

  • 服务发现与注册 Eureka 设计理念

    Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。 1. AP 优于…

    Linux系统 2025年10月7日
  • 企业的六种数据存储合规性策略

    强调合规性的数据存储管理人员应该遵循行业机构分析师推荐的策略,其中包括采用自动化技术和匿名数据。存储专业人士如今有很多事情要做,但在隐私法规范围不断扩展的时代,他们的任务清单却在不…

    Linux系统 2025年6月9日
  • Linux中使用TCP 封装器加强网络服务安全

    在这篇文章中,我们将会讲述什么是 TCP 封装器TCP wrappers以及如何在一台 Linux 服务器上配置他们来限制网络服务的权限。在开始之前,我们必须澄清 TCP 封装器并…

    Linux系统 2025年6月11日
  • Ubuntu 18.04 LTS部署Rsyslog日志服务

    Rsyslog 是一个 syslogd 的多线程增强版。它提供高性能、极好的安全功能和模块化设计。虽然它基于常规的 syslogd,但 rsyslog 已经演变成了一个强大的工具,…

    Linux系统 2025年6月8日
  • 详解RPM 包制作方法

    RPM(RedHat Package Manager)一种通过资料库管理的方式将所需要的软件安装到主机上的管理程序,Linux就是通过rpm来管理和实现软件的安装、查看、删除的。 …

    Linux系统 2025年7月8日
  • Linux下安装PHP的PDO

    PDO(PHP Data Objects)是一种在PHP里连接数据库的使用接口。PDO与mysqli曾经被建议用来取代原本PHP在用的mysql相关函数,基于数据库使用的安全性,因…

    Linux系统 2025年6月26日
  • Linux部署AutoFs挂载服务

    Autofs非常方便,主要有两点: 1、设置开机不一定要挂载的目录,当用的时候才实现自动挂载。 2、用户不使用自动挂载的目录一段的时间,会自动卸载。(默认时间为5分钟) [root…

    Linux系统 2025年6月8日
  • springboot 配置DRUID数据源具体流程

    Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBo…

    Linux系统 2025年10月19日
  • SELinux Targeted、MLS和Minimum策略

    对于 SELinux 来说,所选择的策略类型直接决定了使用哪种策略规则来执行主体(进程)可以访问的目标(文件或目录资源)。不仅如此,策略类型还决定需要哪些特定的安全上下文属性。通过…

    Linux系统 2025年10月22日
  • CentOS7中安装Weblogic具体步骤

    WebLogic是美国Oracle公司出品的一个application server确切的说是一个基于JAVAEE架构的中间件,BEA WebLogic是用于开发、集成、部署和管理…

    Linux系统 2025年6月8日

发表回复

登录后才能评论