互联网协议必备: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 是后端开发中经常进行的工作,这些知识也可以应用到许多其他语言中。掌握好这些技能,可以大大提高我们的开发效率。



目录
相关文章
|
7月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
387 1
|
7月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
362 1
|
8月前
|
XML JSON 编解码
从JSON到Protobuf,深入序列化方案的选型与原理
序列化是数据跨边界传输的“翻译官”,将结构化数据转为二进制流。JSON可读性强但冗余大,Protobuf高效紧凑、性能优越,成主流选择。不同场景需权衡标准化与定制优化,选最合适方案。
537 3
|
8月前
|
机器学习/深度学习 JSON 监控
淘宝拍立淘按图搜索与商品详情API的JSON数据返回详解
通过调用taobao.item.get接口,获取商品标题、价格、销量、SKU、图片、属性、促销信息等全量数据。
|
7月前
|
JSON API 数据格式
淘宝拍立淘按图搜索API系列,json数据返回
淘宝拍立淘按图搜索API系列通过图像识别技术实现商品搜索功能,调用后返回的JSON数据包含商品标题、图片链接、价格、销量、相似度评分等核心字段,支持分页和详细商品信息展示。以下是该API接口返回的JSON数据示例及详细解析:
|
7月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南
|
7月前
|
JSON API 数据安全/隐私保护
Python采集淘宝拍立淘按图搜索API接口及JSON数据返回全流程指南
通过以上流程,可实现淘宝拍立淘按图搜索的完整调用链路,并获取结构化的JSON商品数据,支撑电商比价、智能推荐等业务场景。
|
8月前
|
JSON 缓存 自然语言处理
多语言实时数据微店商品详情API:技术实现与JSON数据解析指南
通过以上技术实现与解析指南,开发者可高效构建支持多语言的实时商品详情系统,满足全球化电商场景需求。
|
8月前
|
JSON API 数据格式
干货满满!淘宝商品详情数据,淘宝API(json数据返回)
淘宝商品详情 API 接口(如 taobao.item.get)的 JSON 数据返回示例如下
|
7月前
|
JSON 中间件 Java
【GoGin】(3)Gin的数据渲染和中间件的使用:数据渲染、返回JSON、浅.JSON()源码、中间件、Next()方法
我们在正常注册中间件时,会打断原有的运行流程,但是你可以在中间件函数内部添加Next()方法,这样可以让原有的运行流程继续执行,当原有的运行流程结束后再回来执行中间件内部的内容。​ c.Writer.WriteHeaderNow()还会写入文本流中。可以看到使用next后,正常执行流程中并没有获得到中间件设置的值。接口还提供了一个可以修改ContentType的方法。判断了传入的状态码是否符合正确的状态码,并返回。在内部封装时,只是标注了不同的render类型。再看一下其他返回的类型;
356 3