go 进阶 三方库之 EasJson 与标准库json

2023-11-04

一. Go 标准库 json

  1. Go 标准库中提供了内置的 JSON 编码和解码功能,可以用于序列化和反序列化 JSON 数据
import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name  string `json:"name"`
    Age   int    `json:"age"`
    Phone string `json:"phone"`
}

func main() {
    // 创建一个 Person 实例
    p := Person{Name: "Tom", Age: 23, Phone: "12345678901"}

    // 使用 json 包中的 Marshal 函数进行序列化
    data, err := json.Marshal(p)
    if err != nil {
        fmt.Println("序列化失败:", err)
    }

    // 完成序列化后打印出得到的 JSON 字符串
    fmt.Println(string(data))

	// 模拟从网络中读取到的 JSON 字符串
    data := `{"name":"Tom","age":23,"phone":"12345678901"}`

    // 使用 json 包中的 Unmarshal 函数进行反序列化
    var p Person
    err := json.Unmarshal([]byte(data), &p)
    if err != nil {
        fmt.Println("反序列化失败:", err)
    }

    // 完成反序列化后打印出得到的 Go 结构体对象
    fmt.Println(p)
}
  1. 一些其它功能
//1.格式化输出 JSON 字符串
func test1() {
    p := Person{Name: "Tom", Age: 23}
    //第二个参数(空字符串)指定了缩进的前缀,而第三个参数(两个空格)指定了每行缩进的内容
    data, err := json.MarshalIndent(p, "", "  ")
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))
}

//2.处理不定层数的 JSON 数据
type Person struct {
    Name      string          `json:"name"`
    Age       int             `json:"age"`
    //它的类型为 json.RawMessage
    ExtraData json.RawMessage `json:"extra_data"`
}

func test2() {
	//定义JSON 字符串其中 extra_data 字段的值是一个嵌套结构
    data := `
        {
            "name": "Tom",
            "age": 23,
            "extra_data": {
                "hobby": ["reading", "music"],
                "address": {
                    "city": "Shanghai",
                    "street": "Nanjing Road"
                }
            }
        }
    `
    var p Person
    err := json.Unmarshal([]byte(data), &p)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(p.Name, p.Age)

    // 处理 extra_data 字段的数据
    //先将 extra_data 解析成 json.RawMessage 类型,
    var extraData map[string]interface{}
    //然后使用 json.Unmarshal 函数再继续解析其它内容
    err = json.Unmarshal(p.ExtraData, &extraData)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(extraData["hobby"])
    fmt.Println(extraData["address"].(map[string]interface{})["city"])
}

//3.自定义 JSON 序列化器,MarshalJSON 函数
func (p Person) MarshalJSON() ([]byte, error) {
    type alias Person
    return json.Marshal(&struct {
    	 //在自定义序列化器中创建了一个别名类型 alias,并将其作为新结构体实例的匿名字段
        *alias
        AgeStr string `json:"age_str"`
    }{
        alias:  (*alias)(&p),
        AgeStr: fmt.Sprintf("%d years old", p.Age),
    })
}

//序列化时结果中新增了一个 age_str 字段,它的值是 Age 字段的字符串形式附加 " years old" 后缀
func main() {
    p := Person{Name: "Tom", Age: 23}
    data, err := json.Marshal(p)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))

    data2, err := json.MarshalIndent(p, "", "  ")
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data2))
}

二. EasJson

  1. Go 标准库中内置的 JSON底层是基于反射实现的,性能较低,推荐使用"github.com/mailru/easyjson"
package main

import (
    "fmt"
	//1.导入依赖
    "github.com/mailru/easyjson"
)

//2.使用 easyjson 标记指定结构体,结构体上方必须要加上"//go:generate"
//并且要执行"go generate"指令,生成的相关代码会被保存在 person_easyjson.go 文件中,如下:
//go:generate easyjson -all person.go
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

//使用示例
func main() {
    p := Person{Name: "Tom", Age: 23}

    // 将 Person 实例序列化为 JSON 字节数组
    data, err := p.MarshalJSON()
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))

    // 将 JSON 字节数组反序列化为 Person 实例
    var p2 Person
    err = p2.UnmarshalJSON(data)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("%+v\n", p2)

	jsonString := `{"name":"Tom","age":23,"address":{"city":"Shanghai","country":"China"}}`
    // 将 JSON 字符串反序列化为 map 类型的数据
    var data map[string]interface{}
    err := easyjson.Unmarshal([]byte(jsonString), &data)
    if err != nil {
        fmt.Println(err)
        return
    }
}
  1. 序列化时忽略空值通过omitempty标签
type Person struct {
    Name string `json:"name,omitempty"`
    Age  int    `json:"age,omitempty"`
}

func main() {
    p := Person{Name: "Tom"}

    // 将 Person 实例序列化为 JSON 字节数组,忽略空值字段
    data, err := easyjson.MarshalWithOptions(&p, easyjson.MarshalOptions{
        UseConstKey: true,
        Indent:      "",
        UnescapeHTML:true,
        OmitEmpty:   true,
    })
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))
}
  1. 自定义序列化和反序列化方法
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func (p *Person) UnmarshalJSON(data []byte) error {
    type Alias Person
    aux := &struct {
        *Alias
    }{
        Alias: (*Alias)(p),
    }
    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }
    p.Name = strings.ToUpper(p.Name)
    return nil
}

func (p *Person) MarshalJSON() ([]byte, error) {
    type Alias Person
    return json.Marshal(&struct {
        *Alias
        Name string `json:"name"`
    }{
        Alias: (*Alias)(p),
        Name:  strings.ToLower(p.Name),
    })
}

func main() {
    p := &Person{Name: "Tom", Age: 23}
    data, err := easyjson.Marshal(p)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))

    p2 := &Person{}
    err = easyjson.Unmarshal(data, p2)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("%+v\n", p2)
}
  1. 支持 slice 和 map 类型的 JSON 序列化和反序列化
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}
func main() {
    people := []Person{
        {Name: "Tom", Age: 23},
        {Name: "Jerry", Age: 25},
    }

    // 将 slice 序列化为 JSON 字节数组
    data, err := easyjson.Marshal(people)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))

    // 将 JSON 字节数组反序列化为 slice
    var people2 []Person
    err = easyjson.Unmarshal(data, &people2)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("%+v\n", people2)
}
  1. easyjson 库在序列化和反序列化时采用对象池技术来减少内存分配次数,从而提升程序性能
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    p := &Person{Name:"Tom", Age:23}
    data, err := easyjson.Marshal(p)
    if err != nil {
        fmt.Println(err)
        return
    }

    var p2 Person
    //easyjson.NewDecoder 创建一个解码器对象
    decoder := easyjson.NewDecoder(bytes.NewReader(data))
    for i := 0; i < 10000; i++ {
        err = decoder.Decode(&p2)
        if err != nil {
            fmt.Println(err)
            return
        }
        // 使用解析结果...
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

go 进阶 三方库之 EasJson 与标准库json 的相关文章

随机推荐

  • 人工智能方向毕业设计_毕业季|广州美术学院视觉设计学院毕业设计展

    视觉艺术设计学院成立于2010年9月 由广州美术学院最传统的装潢系和新兴的数码艺术设计系联合组建而成 2018年11月 艺术与科技专业并入学院 学院现拥有视觉传达设计 数字媒体艺术设计 动画 艺术与科技4个专业 视觉文化设计工作室 视觉文化
  • Java 缓存介绍(Caffeine,EhCache)

    Caffeine 一个高性能的缓存库 Caffeine 使用 Window TinyLfu 回收策略 可以提供了一个近乎最佳的命中率 依赖 maven
  • Open3D(C++) 模型滤波——均值滤波

    目录 一 概述 1 算法原理 2 主要函数 3 算法源码 二 代码实现 三 结果展示 一 概述 1 算法原理 Open3d包含许多网格滤波的算法 最简单的是均值滤波器 该滤波器能用以网格去噪 一个顶点 v i v i v
  • Oracel的多表查询

    笛卡尔积 说到多表查询 我们离不开的就是笛卡尔积的概念 他的作用就是将所有数据无脑的叠加在一起出现了很多没用的数据 他的特点是 笛卡尔积的行数 A表的行数 B表的行数 笛卡尔积的列数 A表额列数 A表的列数 笛卡尔积的数据集合有一些是无效的
  • [ShaderGraph]12.水晶效果

    边缘发光ShaderGraph节点图 内发光ShaderGraph节点图 透明水晶效果ShaderGraph节点图 效果图 节点解析 边缘光的效果不涉及新节点 自发光的涉及到的新节点是One Minus 透视效果涉及的新节点是View Di
  • 深入了解Python 变量作用域

    更多编程教程请到 菜鸟教程 https www piaodoo com 友情链接 好看站 http www nrso net 高州阳光论坛https www hnthzk com 特点 python的作用域是静态的 在源代码中变量名被赋值的
  • python编写知乎爬虫实践

    爬虫的基本流程 网络爬虫的基本工作流程如下 首先选取一部分精心挑选的种子URL 将种子URL加入任务队列 从待抓取URL队列中取出待抓取的URL 解析DNS 并且得到主机的ip 并将URL对应的网页下载下来 存储进已下载网页库中 此外 将这
  • 前端-elemen-ui中el-cascader组件(自定义)

    关于饿了么儿 的cascader组件后端返回的数据与组件里的参数不同如何处理 后端返回的数据 element ui中Cascader 级联选择器组件结构为 参数不一样 修改方法
  • pytest自动化测试框架tep环境变量、fixtures、用例三者之间的关系

    tep是一款测试工具 在pytest测试框架基础上集成了第三方包 提供项目脚手架 帮助以写Python代码方式 快速实现自动化项目落地 在tep项目中 自动化测试用例都是放到tests目录下的 每个 py文件相互独立 没有依赖 1个文件即1
  • 执行shell脚本出现“let:not found”错误以及解决办法

    问题描述 在写一个脚本循环时候 出现 let not found 这是因为在ubuntu默认是指向bin dash解释器的 dash是阉割版的bash 其功能远没有bash强大和丰富 并且dash不支持let和i 等功能 解决办法 打开一个
  • 消息队列MQ-面试题

    目录 1 什么是消息队列 2 为什么要使用消息队列 1 解耦 2 异步处理 3 削峰 3 使用消息队列带来的一些问题 4 JMS两种消息模型 5 消息队列由哪些角色组成 6 常见消息中间件比较 7 如何保证消息队列是高可用的 RocketM
  • vue开发过程中node和sass互相对应的版本

    点击查看官网node sass和node对应的版本 1 点击查看稳定版链接 2 点击查看拓展版链接 1 检查node版本 2 删除node modules 3 保留原始的package json文件 4 安装node sass 5 安装sa
  • 二维码生成+解码

    在线二维码解码器 二维码安全检测工具 如下
  • Apache Struts2漏洞复现之s2-005漏洞复现

    0x01 声明 仅供学习参考使用 请勿用作违法用途 否则后果自负 0x02 简介 Apache Struts 2是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构 它利用并延伸了Java ServletAPI 鼓励开发者采
  • Kafka零拷贝

    Kafka除了具备消息队列MQ的特性和使用场景外 它还有一个重要用途 就是做存储层 用kafka做存储层 为什么呢 一大堆可以做数据存储的 MySQL MongoDB HDFS 因为kafka数据是持久化磁盘的 还速度快 还可靠 支持分布式
  • 头文件中的ifndef/define/endif的作用

    防止该头文件被重复引用 标识的命名规则一般是头文件名全大写 前后加下划线 并把文件名中的 也变成下划线 如 stdio h define STDIO H 例子 Define CRTIMP ifndef CRTIMP ifdef DLL de
  • jdbc操作Date类型时的比较

    有些oracle数据库查出日期时得到的结果是不一样的 select from table t where t attentionTime to date 2015 09 15 yyyy mm dd 这样的查询语句在一个数据库有时是可以查到有
  • Javascript中函数的形参和函数内局部变量同名的问题

    前言上次牛客网做到这样一个题 非常有意思 陷阱非常多 当时觉得搞明白了 现在再看到 又糊涂了 发现了新的点 看一下 var foo n 1 function foo console log foo n foo n 3 var foo n 2
  • SpringBoot系列 logback-spring日志配置使用记录以及解决依赖包冲突问题

    SpringBoot推荐使用logback spring xml SpringBoot官方推荐使用logback spring xml作为logback框架的自定义日志配置文件 例如 使用logback spring xml而不是logba
  • go 进阶 三方库之 EasJson 与标准库json

    目录 一 Go 标准库 json 二 EasJson 一 Go 标准库 json Go 标准库中提供了内置的 JSON 编码和解码功能 可以用于序列化和反序列化 JSON 数据 import encoding json fmt type P