新闻中心
Go语言中json.Marshal的正确使用:解决空JSON输出与字节切片困惑

本文深入探讨go语言中encoding/json包的json.marshal函数在使用时常遇到的两个核心问题:结构体字段未导出导致生成空json对象,以及json.marshal返回字节切片而非直接的字符串。通过详细的解释和代码示例,我们将学习如何正确地定义可序列化的结构体,并处理json.marshal的输出,从而生成预期的json字符串。
理解Go语言的JSON序列化机制
在Go语言中,encoding/json包提供了强大的功能,用于将Go结构体转换为JSON格式(序列化或编码),以及将JSON数据解析回Go结构体(反序列化或解码)。json.Marshal函数是实现序列化的核心工具。然而,初学者在使用该函数时,常常会遇到一些看似“奇怪”的输出,例如得到空的JSON对象{}或一串数字[123 125]。这通常源于对Go语言的可见性规则和json.Marshal返回类型的不完全理解。
问题一:结构体字段未导出导致空JSON输出
json.Marshal在将Go结构体序列化为JSON时,默认只会处理结构体中已导出(Exported)的字段。在Go语言中,一个字段是否导出,取决于其名称的首字母大小写:
- 首字母大写:表示该字段是已导出的(Public),可以在包外部访问,并且json.Marshal可以对其进行序列化。
- 首字母小写:表示该字段是未导出的(Private),只能在定义它的包内部访问,json.Marshal无法访问和序列化这些字段。
当结构体中所有希望被序列化的字段都是未导出时,json.Marshal将无法找到任何可序列化的数据,因此会生成一个空的JSON对象{}。
示例:错误的使用方式
考虑以下结构体定义:
package main
import (
"encoding/json"
"fmt"
)
type Zoo struct {
name string // 未导出字段
animals []Animal // 未导出字段
}
type Animal struct {
species string // 未导出字段
says string // 未导出字段
}
func main() {
zoo := Zoo{
name: "Magical Mystery Zoo",
animals: []Animal{
{"Cow", "Moo"},
{"Cat", "Meow"},
{"Fox", "???"},
},
}
zooJson, err := json.Marshal(zoo)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("原始结构体:", zoo)
fmt.Println("json.Marshal 输出:", string(zooJson)) // 转换为字符串以便查看
}上述代码的输出将是:
原始结构体: {Magical Mystery Zoo [{Cow Moo} {Cat Meow} {Fox ???}]}
json.Marshal 输出: {}尽管zoo结构体本身包含数据,但json.Marshal输出的JSON却是空的{},原因就是Zoo和Animal结构体中的所有字段(name, animals, species, says)都是首字母小写的未导出字段。
解决方案一:导出结构体字段
要解决这个问题,只需将结构体中需要序列化的字段首字母改为大写,使其成为已导出字段。
package main
import (
"encoding/json"
"fmt"
)
type Zoo struct {
Name string // 已导出字段
Animals []Animal // 已导出字段
}
type Animal struct {
Species string // 已导出字段
Says string // 已导出字段
}
func main() {
zoo := Zoo{
Name: "Magical Mystery Zoo",
Animals: []Animal{
{"Cow", "Moo"},
{"Cat", "Meow"},
{"Fox", "???"},
},
}
zooJson, err := json.Marshal(zoo)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("原始结构体:", zoo)
fmt.Println("json.Marshal 输出:", string(zooJson))
}现在,json.Marshal将能够正确地访问并序列化这些字段,输出将接近预期:
小云雀
剪映出品的AI视频和图片创作助手
1949
查看详情
原始结构体: {Magical Mystery Zoo [{Cow Moo} {Cat Meow} {Fox ???}]}
json.Marshal 输出: {"Name":"Magical Mystery Zoo","Animals":[{"Species":"Cow","Says":"Moo"},{"Species":"Cat","Says":"Meow"},{"Species":"Fox","Says":"???"}]}使用JSON Tag自定义字段名
如果希望JSON输出的字段名与Go结构体字段名不同(例如,Go中使用驼峰命名,JSON中使用蛇形命名),可以使用结构体标签(json tag)来指定。
type Zoo struct {
Name string `json:"zoo_name"` // JSON输出时字段名为 "zoo_name"
Animals []Animal `json:"animals"`
}
type Animal struct {
Species string `json:"species_name"`
Says string `json:"sound"`
}这样,JSON输出会变成:
{
"zoo_name": "Magical Mystery Zoo",
"animals": [
{
"species_name": "Cow",
"sound": "Moo"
},
{
"species_name": "Cat",
"sound": "Meow"
},
{
"species_name": "Fox",
"sound": "???"
}
]
}问题二:json.Marshal返回字节切片[]byte
另一个常见的困惑是fmt.Println(zooJson)直接输出一串数字,如[123 125],而不是可读的JSON字符串。这是因为json.Marshal函数的设计:它返回的是一个字节切片([]byte),而不是一个Go字符串(string)。
[123 125]实际上是ASCII码,123代表字符{,125代表字符}。这意味着在字段未导出的情况下,json.Marshal生成了空的JSON对象{},并将其以字节切片的形式返回。当直接打印[]byte时,fmt.Println会默认打印其内部的字节数值表示。
解决方案二:将字节切片转换为字符串
要查看json.Marshal生成的JSON内容,需要将返回的[]byte显式地转换为string类型。
package main
import (
"encoding/json"
"fmt"
)
type Zoo struct {
Name string
Animals []Animal
}
type Animal struct {
Species string
Says string
}
func main() {
zoo := Zoo{
Name: "Magical Mystery Zoo",
Animals: []Animal{
{"Cow", "Moo"},
{"Cat", "Meow"},
{"Fox", "???"},
},
}
zooJson, err := json.Marshal(zoo)
if err != nil {
fmt.Println("Error:", err)
return
}
// 正确的做法:将 []byte 转换为 string
fmt.Println("序列化后的JSON字符串:", string(zooJson))
// 如果需要格式化输出,可以使用 json.MarshalIndent
prettyJson, err := json.MarshalIndent(zoo, "", " ")
if err != nil {
fmt.Println("Error formatting JSON:", err)
return
}
fmt.Println("格式化后的JSON字符串:\n", string(prettyJson))
}输出将是:
序列化后的JSON字符串: {"Name":"Magical Mystery Zoo","Animals":[{"Species":"Cow","Says":"Moo"},{"Species":"Cat","Says":"Meow"},{"Species":"Fox","Says":"???"}]}
格式化后的JSON字符串:
{
"Name": "Magical Mystery Zoo",
"Animals": [
{
"Species": "Cow",
"Says": "Moo"
},
{
"Species": "Cat",
"Says": "Meow"
},
{
"Species": "Fox",
"Says": "???"
}
]
}通过string(zooJson),我们得到了可读的JSON字符串。此外,json.MarshalIndent函数可以帮助我们生成带有缩进的、更易读的JSON格式。
总结与注意事项
- 导出字段是关键:确保所有需要被json.Marshal序列化的结构体字段都以大写字母开头,成为已导出字段。
- []byte到string的转换:json.Marshal返回的是[]byte类型,要以字符串形式查看其内容,务必使用string()进行类型转换。
- 错误处理:json.Marshal和json.MarshalIndent都可能返回错误,尤其是在处理复杂或循环引用的数据结构时。始终检查err返回值是一个良好的编程习惯。
- JSON Tag:利用结构体标签(json:"fieldName")可以灵活地控制JSON输出的字段名,甚至可以通过json:"-"忽略特定字段,或通过json:",omitempty"在字段为空值时省略该字段。
理解并遵循这些原则,可以有效避免在使用Go语言进行JSON序列化时常见的陷阱,确保程序能够正确、高效地处理JSON数据。
以上就是Go语言中json.Marshal的正确使用:解决空JSON输出与字节切片困惑的详细内容,更多请关注其它相关文章!
# 的是
# 生发液的营销推广
# 利于seo商城系统
# 南开区网站推广团队
# 新民seo优化软件
# 新沂网站排名优化
# 如何建设电商网站流程
# 南通网站建设报告
# 安庆关键词排名优化哪家靠谱
# 东莞新站seo方案
# 鸡西网站优化商铺出租
# 将是
# 字段名
# 是一个
# 都是
# js
# 数据结构
# 首字母
# 加载
# 转换为
# 序列化
# string类
# 格式化输出
# ai
# 工具
# 字节
# 编码
# go语言
# go
# json
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
outlook中文官网入口地址 outlook官方中文版直达首页链接
现代化 SciPy 一维插值:interp1d 的替代方案与最佳实践
不同用户不同价格! 索尼开启账户个性化定价测试
微信群消息显示延迟如何解决 微信群消息刷新优化方法
CSS Flexbox与媒体查询:实现响应式布局中元素的并排与堆叠
Typer应用中灵活处理命令行参数的令牌化与解析
Pandas DataFrame:高效添加条件计算列
深入理解Promise链:如何在catch后中断then的执行
拼多多购物车商品数量无法修改如何处理 拼多多购物车操作优化方法
响应式图片在网页设计中的正确实现方法
J*a TimerTask文件监控:HashMap状态管理与常见陷阱规避指南
CSS布局中意外空白:解决padding-top导致的顶部间距问题
如何将HTML表格多行数据保存到Google Sheets
TikTok评论显示延迟如何处理 TikTok评论刷新优化方法
Basecamp怎样用留言钉固定重点_Basecamp用留言钉固定重点【重点标记】
押井守高度称赞《辐射4》:玩了八年都停不下来!
sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置
如何在 Excel Online 和 Google 表格中更改日期格式
Golang指针如何与map组合使用_Golang map指针组合实践
AngularJS $http POST请求数据传递与Go后端接收实践
Go Martini框架:动态服务解码后的图片内容
Node.js中HTML按钮与J*aScript函数交互的正确姿势
必由学官网快捷入口 必由学网页版在线学习平台
KFC早餐时段怎么领特惠代码_KFC早餐订餐优惠代码获取与使用说明
b站怎么删除评论_b站评论管理与删除操作
在Typer应用中优雅地处理和重组任意命令行参数
uc浏览器网页版极速入口 uc网页浏览器网页版流畅体验
微信商城在哪里打开【步骤】
想当下一个《2077》?《心之眼》Steam评价升至"多半好评"
俄罗斯Yandex免登录入口_Yandex搜索引擎官网一键直达
优化大型XML文件解析:基于Python流式处理的内存高效方案
qq游戏手机版下载安装_qq游戏移动端入口
俄罗斯Yandex搜索引擎入口_Yandex官网免登录一键访问
实现全屏滚动与导航点:专业教程
快手官方唯一登录入口 谨防山寨钓鱼网站
Sublime Text怎么显示空格和制表符_Sublime显示不可见字符设置
Win11怎么安装Linux子系统 Win11 WSL2安装Ubuntu及环境配置指南
J*aScript中高效管理与清空动态列表:避免循环陷阱
京东单号查询入口_京东快递订单追踪入口
狙击外星人小游戏开始_狙击外星人小游戏立即开始
苹果手机指南针不准怎么校准 传感器校准方法详解【建议收藏】
AO3官方在线访问地址 Archive of Our Own最新镜像合集
Python实现多节点属性重叠度分析教程
QQ邮箱官方网站登录入口_QQ邮箱网页版在线使用
QQ邮箱网页版登录入口 QQ邮箱官方在线使用平台
谷歌邮箱网页版官方页面入口 谷歌邮箱网页端快速访问
mysql通配符支持数字匹配吗_mysql通配符能否用于数字匹配的解析
邮政快递包裹最新位置 邮政快递实时追踪入口
PPT平滑切换怎么做 PPT炫酷“平滑”切换动画制作教程【必学】
Selenium Python中处理点击后新窗口加载冻结问题的策略与实践


2025-11-20
浏览次数:次
返回列表
},
{
"Species": "Cat",
"Says": "Meow"
},
{
"Species": "Fox",
"Says": "???"
}
]
}