1.软文推荐

2.软文推荐

3.软文推荐

目前我们看到很多的开放平台,基本上都是采用了JSON作为他们的数据交互的格式。既然JSON在Web开发中如此重要,那么Go语言对JSON支持的怎么样呢?Go语言的标准库已经非常好的支持了JSON,可以很容易的对JSON数据进行编、解码的工作。如果有更灵活的需求也有不错的第三方库提供支持。这篇文章将全面解读Golang中JSON的使用。

基本的序列化

首先我们来看一下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
", err)
return
}
fmt.Printf("str:%s
", b)
// json string -> struct
var p2 Person
err = json.Unmarshal(b, &p2)
if err != nil {
fmt.Printf("json.Unmarshal failed, err:%v
", err)
return
}
fmt.Printf("p2:%#v
", 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
", err)
return
}
fmt.Printf("str:%s
", 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
", err)
return
}
fmt.Printf("str:%s
", 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
", err)
return
}
fmt.Printf("str:%s
", 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
", err)
return
}
fmt.Printf("c1:%#v
", c1) // c1:main.Card{ID:1234567, Score:88.5}
}

本文来源:www.lxlinux.net/9208.html,若引用不当,请联系修改。

相关文章 8

1

Linux下实时监控日志文件 3分钟前

如何在Linux中实时查看日志文件的内容?有很多实用工具可以帮助用户在文件修改或不断更新时跟踪或监控文件发生的变化,本篇文章为大家...

2

迁移企业服务器,这八个方面一定要留意(服务器搬迁公司) 4分钟前

迁移企业服务器,这八个方面一定要留意。网络服务器迁移是以便融入网站经营规模持续增长的所产生的更大要求,迁移全过程中,免不了...

3

iON Cloud:美国洛杉矶/圣荷塞VPS年付75折,CN2 GIA线路(cloudnola) 5分钟前

iON Cloud怎么样? iON是Krypt旗下的商家,所以理所当然就是KT机房了,KT机房在IDC行业还是比较知名的,机器非常稳定,网络到国内是非常好的...

4

Ubuntu中卸载OpenSSL具体方法 7分钟前

本篇文章重点为大家讲解一下Ubuntu中卸载OpenSSL具体方法,有需要的小伙伴可以参考一下。 卸载原有 openssl 版本 #sudoapt-getremoveopenssl 下载最新...

5

通过镜像安装pytorch 8分钟前

Pytorch是torch的python版本,是由Facebook开源的神经网络框架,专门针对 GPU 加速的深度神经网络(DNN)编程。 1.安装anacoda 这网上已有许多教程...

6

Contabo:美国西雅图vps/最具性价比VPS;4核/8G内存/200G SSD,4.99/月起(美国contigo) 9分钟前

contabo怎么样? contabo是一家运营了20多年的欧洲老牌主机商,之前一直是以德国本土数据中心为主,目前已经扩展到全球5 个地区,8 个地点...

7

详解JSP-调试 10分钟前

jsp即java server pages,顾名思义就是java服务器端页面,是一种动态的页面开发技术。并且jsp实现了html中插入java代码的技术,是放在服务器端的...

8

腾讯云服务器618活动:企业新用户低至0.6折,2核4G3M仅363元/年(腾讯云服务器学生优惠) 10分钟前

腾讯云服务器618活动: 云服务器首年95元起,更有总价值6188元代金券免费领,企业专享优惠产品低至1折起,其中2核4G3M云服务器仅需363元...