基本的序列化

在Go语言中json.Marshal()(系列化)与json.Unmarshal(反序列化)的基本用法

type Person struct {Name   stringAge    int64Weight float64
}func main() {p1 := Person{Name:   "奇奇",Age:    18,Weight: 55.5,}// struct -> json stringb, 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 -> structvar p2 Personerr = 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":55.5}
p2:main.Person{Name:"奇奇", Age:18, Weight:55.5}

tag的介绍以及用法

虽然平时很少用到,但是感觉还是很方便的样子,以后可以巧妙的应用
Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来。
Tag在结构体字段的后方定义,由一对反引号包裹起来,具体的格式如下:

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

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

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

    // 使用json tag指定序列化与反序列化时的行为
    type Person struct {Name   string `json:"name"` // 指定json序列化/反序列化时使用小写nameAge    int64Weight float64
    }
    
  • 忽略某个字段
    如果你想在json序列化/反序列化的时候忽略掉结构体中的某个字段,可以按如下方式在tag中添加-

    // 使用json tag指定json序列化与反序列化时的行为
    type Person struct {Name   string `json:"name"` // 指定json序列化/反序列化时使用小写nameAge    int64Weight 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 stringb, 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"`
    }
    

    来来来,看效果了

    str:{"name":"奇奇"} // 序列化结果中没有email和hobby字段
    
  • 首先来看几种结构体嵌套的示例:
    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数据中可能会使用字符串类型的数字,这个时候可以在结构体tag中添加string来告诉json包从字符串中解析相应字段的数据:

    type Card struct {ID    int64   `json:"id,string"`    // 添加string tagScore float64 `json:"score,string"` // 添加string tag
    }func intAndStringDemo() {jsonStr1 := `{"id": "1234567","score": "88.50"}`var c1 Cardif 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}
    }
    

整数变浮点数

  • 在 JSON 协议中是没有整型和浮点型之分的,它们统称为number。json字符串中的数字经过Go语言中的json包反序列化之后都会成为float64类型。下面的代码便演示了这个问题:

    func jsonDemo() {// map[string]interface{} -> json stringvar m = make(map[string]interface{}, 1)m["count"] = 1 // intb, err := json.Marshal(m)if err != nil {fmt.Printf("marshal failed, err:%v\n", err)}fmt.Printf("str:%#v\n", string(b))// json string -> map[string]interface{}var m2 map[string]interface{}err = json.Unmarshal(b, &m2)if err != nil {fmt.Printf("unmarshal failed, err:%v\n", err)return}fmt.Printf("value:%v\n", m2["count"]) // 1fmt.Printf("type:%T\n", m2["count"])  // float64
    }
    
  • 这种场景下如果想更合理的处理数字就需要使用decoder去反序列化,示例代码如下:
    func decoderDemo() {// map[string]interface{} -> json stringvar m = make(map[string]interface{}, 1)m["count"] = 1 // intb, err := json.Marshal(m)if err != nil {fmt.Printf("marshal failed, err:%v\n", err)}fmt.Printf("str:%#v\n", string(b))// json string -> map[string]interface{}var m2 map[string]interface{}// 使用decoder方式反序列化,指定使用number类型decoder := json.NewDecoder(bytes.NewReader(b))decoder.UseNumber()err = decoder.Decode(&m2)if err != nil {fmt.Printf("unmarshal failed, err:%v\n", err)return}fmt.Printf("value:%v\n", m2["count"]) // 1fmt.Printf("type:%T\n", m2["count"])  // json.Number// 将m2["count"]转为json.Number之后调用Int64()方法获得int64类型的值count, err := m2["count"].(json.Number).Int64()if err != nil {fmt.Printf("parse to int64 failed, err:%v\n", err)return}fmt.Printf("type:%T\n", int(count)) // int
    }
    

处理不确定层级的json

  • 如果json串没有固定的格式导致不好定义与其相对应的结构体时,我们可以使用json.RawMessage原始字节数据保存下来。

    type sendMsg struct {User string `json:"user"`Msg  string `json:"msg"`
    }func rawMessageDemo() {jsonStr := `{"sendMsg":{"user":"q1mi","msg":"永远不要高估自己"},"say":"Hello"}`// 定义一个map,value类型为json.RawMessage,方便后续更灵活地处理var data map[string]json.RawMessageif err := json.Unmarshal([]byte(jsonStr), &data); err != nil {fmt.Printf("json.Unmarshal jsonStr failed, err:%v\n", err)return}var msg sendMsgif err := json.Unmarshal(data["sendMsg"], &msg); err != nil {fmt.Printf("json.Unmarshal failed, err:%v\n", err)return}fmt.Printf("msg:%#v\n", msg)// msg:main.sendMsg{User:"q1mi", Msg:"永远不要高估自己"}
    }
    

go语言json使用技巧相关推荐

  1. go语言json的使用技巧

    本文整理了一部分我们平时在项目中经常遇到的关于go语言JSON数据与结构体之间相互转换的问题及解决办法. 基本的序列化 首先我们来看一下Go语言中json.Marshal()(系列化)与json.Un ...

  2. 你需要知道的那些go语言json技巧

    本文总结了我平时在项目中遇到的那些关于go语言JSON数据与结构体之间相互转换的问题及解决办法. 基本的序列化 首先我们来看一下Go语言中json.Marshal()(系列化)与json.Unmars ...

  3. python映射的主要特点_30 个 Python 语言的特点技巧

    列表按难度排序,常用的语言特征和技巧放在前面. 1.1 分拆 >>> a, b, c = 1, 2, 3 >>> a, b, c (1, 2, 3) >> ...

  4. 计算机c1 c语言答题,全国计算机级考试二级C语言上机答题技巧.doc

    全国计算机等级考试二级C语言上机答题技巧 1.上机改错的试题中通常包含两个(或三个)错误需要修改. 2.试题中用"******found******/"来提示在下一行(或下面第二行 ...

  5. Linux系统下计算机C语言的编程技巧

    C语言在多程序编辑中发挥着基础性作用,并在国际范围得到了全面应用.科技的蓬勃发展,使得人们更加重视C语言技术,并对C语言提出更多的要求.但Linux系统是最主要的操作系统之一,基于此开展C语言编程工作 ...

  6. go语言JSON验证器

    go语言JSON验证器 转自:http://studygolang.com/articles/9621 分析 既然要验证JSON的有效性,那么必然需要清楚的知道JSON格式,这个在JSON官网已经给我 ...

  7. 易语言json置入_易语言json操作模块源码

    易语言json操作模块源码 系统结构:初始化,解析,到文本,置属性,置属性对象,置属性数值,取属性数值,取属性对象,取通用属性,取属性,成员数,加成员,取成员,取成员文本,置成员,删成员,置类型,赋值 ...

  8. C语言常用编程技巧-结构体数组

    本文主要用来记录C语言常用编程技巧,完成一下目的: 1.函数指针如何定义使用: 2.结构体数组如何定义使用: 3.callback 方法使用技巧: 以下代码为在ubuntu 系统进行编译,文件名为 s ...

  9. c语言编程小技巧-if空语句用法

    c语言编程小技巧-if空语句用法 关于if语句其实我们在进行c语言编程的时候用的很多,对于if语句其实有一些小技巧可以帮助我们进行一些更简单的编程 一个小技巧就是我们可以设置条件的对立面来简化我们的编 ...

最新文章

  1. 紧急更新下降难度,《王者荣耀》绝悟 AI 难倒一片玩家
  2. 微服务架构转型需要关注的运维监控的技术和建议
  3. 学习笔记TF064:TensorFlow Kubernetes
  4. JSP内置对象-page
  5. C#枚举中的位运算权限分配浅谈
  6. [ZJOI2008]瞭望塔
  7. 分布式系统原理 之6 两阶段提交协议
  8. 【C++编程题1】数组指针之字符串排序
  9. springboot集成jsp
  10. 正则表达式匹配多个字符串中的一个
  11. tomcat7 加载el表达式 报错 使用tomcat8得以解决
  12. MATLAB安装与解密
  13. NAT协议(网络地址转换协议)详解
  14. 博士申请 | 皇家墨尔本理工大学鲍芝峰教授招收数据挖掘方向全奖博士生
  15. HP Gen8 MicroServer win7 系统安装手册(usb)
  16. java设计模式总结1
  17. java-web实训项目:simonshop(3)Servlet层
  18. 计算机cpu的字母,电脑处理器后面的字母你认识几个?不认识跟我来学学(intel篇)...
  19. 怎么保存网页为html格式,怎样保存网页部分内容为html格式?
  20. Spring入门-1-基本配置和IOC、DI

热门文章

  1. 洛谷P3957 跳房子(玩转单调队列)
  2. office2010安装教程
  3. Ubuntu下Python使用指南
  4. SPWM中三次谐波注入幅值的计算
  5. 亲测软著申请,时间线是这样的。
  6. Flink教程(01)- Flink知识图谱
  7. ACM——二分、三分
  8. 三款大四学生必备PDF阅读器,国产也可以很牛x
  9. 授人以“鱼”,不如授人以“渔”,放弃一个目标,设定另一个目标
  10. 基于Python的结构力学位移法编程求解