互联网协议必备:Go语言中JSON的序列化与反序列化

简介: 互联网协议必备:Go语言中JSON的序列化与反序列化

/ Go 语言将结构体序列化和存储为 JSON 数据指南 /


 

一、概述

JSON 是一种非常流行的数据交换格式,在 Go 语言中经常需要将结构体实例序列化为 JSON 字符串保存和传输。本文将详细介绍如何使用 Go 语言中的 encoding/json 包将结构体序列化为 JSON 数据。

主要内容包括:

  • JSON 序列化概述
  • 定义可序列化的结构体
  • 使用 json.Marshal 序列化
  • 定制序列化逻辑
  • 使用 json.Unmarshal 反序列化
  • 处理空值和默认值
  • 嵌套对象和匿名字段
  • 序列化 interface{}
  • stream 编码器
  • JSON 与 XML 对比
  • 文本格式的优点
  • 使用规范
  • 序列化性能优化

通过本文可以全面了解 Go 语言中处理 JSON 的知识,及如何使用 json 包将结构体快速序列化为 JSON。


 

二、JSON 序列化概述

JSON 是一种非常流行的结构化数据格式,被广泛用于各种网络传输和数据存储之中。

Go 语言中主要通过 json 包来处理 JSON 数据,其中两个核心函数:

  • json.Marshal 序列化 Go 对象为 JSON 格式字节流
  • json.Unmarshal JSON 数据解析为 Go 对象

十分方便地实现序列化与反序列化。


 

三、定义可序列化的结构体

要将一个结构体实例序列化为 JSON,需要确保结构体字段可被 json 包访问,通常有两种方式:

  1. 字段首字母大写,则可以被外部包访问

  2. 通过 tag 指定 json 字段名

一个例子:

type User struct {
  ID int `json:"id"`
  Name string `json:"name"` 
  Age int
}


这样 User 结构体可以正确序列化和反序列化。


 

四、使用 json.Marshal 序列化

将对象编码为 JSON 字节流十分简单:

package main
import (
  "encoding/json"
  "fmt"
)
type User struct {
  Name string `json:"name"`
  Age  int    `json:"age"`
}
func main() {
  user := User{"John", 20}
  // 序列化
  buf, err := json.Marshal(user)
  if err != nil {
    fmt.Println(err)
    return
  }
  // 打印JSON
  fmt.Println(string(buf))
}


运行结果:

{"name":"John","age":20}

通过 json.Marshal 即可将结构体序列化。


 

五、定制序列化逻辑

如果需要控制序列化的细节,可以实现 Marshaler 接口:

package main
import (
  "encoding/json"
  "fmt"
)
type User struct {
  Name string `json:"name"`
  Age  int    `json:"age"`
}
// 实现Marshaler接口
func (u User) MarshalJSON() ([]byte, error) {
  return []byte(fmt.Sprintf(`{"name":"%s"}`, u.Name)), nil
}
func main() {
  u := User{"John", 20}
  jsonBytes, _ := json.Marshal(u)
  fmt.Println(string(jsonBytes)) // {"name":"John"}
}


这样我们可以灵活控制各字段的编码过程。


 

六、使用 json.Unmarshal 反序列化

对于反序列化 JSON 解析为 Go 对象,可以简单的调用 json.Unmarshal:

package main
import (
  "encoding/json"
  "fmt"
)
type User struct {
  Name string `json:"name"`
  Age  int    `json:"age"`
}
func main() {
  jsonStr := `{"name":"John","age":20}`
  // 反序列化到user
  var user User
  err := json.Unmarshal([]byte(jsonStr), &user)
  if err != nil {
    fmt.Println(err)
    return 
  }
  fmt.Println(user.Name) // John
  fmt.Println(user.Age) // 20 
}

传入 JSON 数据以及对象指针,即可解析为对应对象。


 

七、处理空值和默认值

对于空值的序列化,默认会忽略空值字段:

type User struct {
  Name string
  Age  int
}
u := User{"John", 0} 
jsonBytes, _ := json.Marshal(u)
fmt.Println(string(jsonBytes)) // {"Name":"John"}

但可以通过定义 MarshalJSON 方法自定义处理空值的编码。

反序列化时,需要处理不存在的字段,可以使用指针或默认值。


 

八、嵌套对象和匿名字段

对于嵌套的对象字段和内嵌匿名类型,也可以正常序列化和反序列化:

type Info struct {
  Addr string
}
type User struct {
  Info // 嵌套Info
  Name string
}
u := User{Info{"Beijing"}, "Tom"}
jsonBytes, _ := json.Marshal(u)
fmt.Println(string(jsonBytes)) // {"Addr":"Beijing","Name":"Tom"}

编码后嵌套的类型将被内联到结果中。


 

九、序列化 interface{}

json 包可以处理任意的 interface{}值:

data := map[string]interface{}{
  "name": "John",
  "age": 20,
}
jsonBytes, _ := json.Marshal(data)
fmt.Println(string(jsonBytes))

但编码结果会包含类型信息和 Base64 编码后的值。这比定制序列化更低效。


 

十、stream 编码器

我们也可以使用 streaming 模式的 encoder 来进行序列化:


package main
import (
  "encoding/json"
  "os"
)
func main() {
  type User struct {
    Name string
    Age  int
  }
  user := User{"John", 20}
  // 使用stream encoder
  enc := json.NewEncoder(os.Stdout)
  enc.Encode(user)
}

这种编码方式非常灵活,可实现各种自定义输出格式。


 

十一、JSON 与 XML 对比

相比 XML,JSON 具有以下优点:

  • 读取和解析更加方便快捷
  • 存储占用更小且具有可读性
  • 支持更多语言与平台
  • 性能和解析速度更快

这使得 JSON 成为主流的数据交换格式。


 

十二、文本格式的优点

JSON 与其他二进制序列化格式相比,文本格式 JSON 有以下优势:

  • 可读性强,便于打印调试
  • 可复用现有文本处理工具
  • 不依赖语言和平台
  • 可支持部分更新修改

这些特点使 JSON 很适合作为配置、通信和数据存储格式。


 

十三、使用规范

使用 JSON 时,也应注意遵守一定规范:

  • 格式化打印 JSON 数据
  • 为类型和字段定义 Canonical 名称
  • 提供完整的文档
  • 版本控制 JSON 接口
  • 采用更灵活的 schema 描述

这可以确保使用 JSON 的稳定性和兼容性。


 

十四、序列化性能优化

对于性能敏感的场景,可以通过以下技巧优化序列化:

  • 提前指定好对象大小
  • 重用分配的内存
  • 尽量避免解析嵌套数据
  • 按需完成自定义编码

针对特定用例微优化这些方面可以提升 JSON 处理的性能。


 

十五、总结

JSON 作为平台无关的数据交换格式,在 Go 语言中有着广泛的应用。本文详细介绍了 Go 语言序列化结构体为 JSON 的知识,希望大家可以运用自如。

管理和转换 JSON 是后端开发中经常进行的工作,这些知识也可以应用到许多其他语言中。掌握好这些技能,可以大大提高我们的开发效率。



目录
相关文章
|
8月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
408 1
|
8月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
383 1
|
9月前
|
XML JSON 编解码
从JSON到Protobuf,深入序列化方案的选型与原理
序列化是数据跨边界传输的“翻译官”,将结构化数据转为二进制流。JSON可读性强但冗余大,Protobuf高效紧凑、性能优越,成主流选择。不同场景需权衡标准化与定制优化,选最合适方案。
576 3
|
11月前
|
JSON 人工智能 Go
在Golang中序列化JSON字符串的教程
在Golang中,使用`json.Marshal()`可将数据结构序列化为JSON格式。若直接对JSON字符串进行序列化,会因转义字符导致错误。解决方案包括使用`[]byte`或`json.RawMessage()`来避免双引号被转义,从而正确实现JSON的序列化与反序列化。
623 7
|
XML JSON Java
go语言之JSON序列化
本文介绍了Go语言中的JSON序列化与反序列化,其操作与Java类似。需要注意的是,由于Go语言的包管理机制,变量和引入包的首字母需大写,以便其他包引用。示例代码展示了如何将`Student`结构体进行JSON序列化(返回字节数组,需转为字符串)及反序列化。此外,文章还说明了通过tag(如`json`和`xml`)指定序列化变量的重要性,以避免因包间访问限制导致反序列化失败或值为null的问题。
226 0
|
JSON JavaScript 前端开发
Go语言JSON 序列化与反序列化 -《Go语言实战指南》
本文介绍了 Go 语言中使用 `encoding/json` 包实现 JSON 与数据结构之间的转换。内容涵盖序列化(`Marshal`)和反序列化(`Unmarshal`),包括基本示例、结构体字段标签的使用、控制字段行为的标签(如 `omitempty` 和 `-`)、处理 `map` 和切片、嵌套结构体序列化、反序列化未知结构(使用 `map[string]interface{}`)以及 JSON 数组的解析。最后通过表格总结了序列化与反序列化的方法及类型要求,帮助开发者快速掌握 JSON 数据处理技巧。
|
JSON 数据格式
【Groovy】json 字符串反序列化 ( 使用 JsonSlurper 进行 json 字符串反序列化 | 根据 map 集合构造相关类 )
【Groovy】json 字符串反序列化 ( 使用 JsonSlurper 进行 json 字符串反序列化 | 根据 map 集合构造相关类 )
1501 155
【Groovy】json 字符串反序列化 ( 使用 JsonSlurper 进行 json 字符串反序列化 | 根据 map 集合构造相关类 )
|
XML 存储 JSON
c#XML、JSON的序列化和反序列化,看完你就懂了
c#XML、JSON的序列化和反序列化,看完你就懂了
726 0
|
存储 JSON JavaScript
Python中的JSON与Pickle模块:数据序列化和反序列化的利器
在Python编程中,数据的序列化和反序列化是经常遇到的操作。序列化是将数据结构或对象状态转换为可以存储或传输的格式的过程,而反序列化则是这个过程的逆操作,即将序列化的数据重新转换回原来的数据结构或对象状态。Python中的JSON和Pickle模块就是实现数据序列化和反序列化的强大工具。
|
JSON Java Maven
使用Jackson进行 JSON 序列化和反序列化
使用Jackson进行 JSON 序列化和反序列化
682 0

热门文章

最新文章