go 中解析JSON的三种姿势
背景
示例Json
{
"userName":"admin",
"nick_name":"管理员",
"info":{
"age":18
},
"extra":[
{
"address":"上海市"
},
{
"address":"北京市"
}
]
}
我们来看看,如何在go中解析。
例子
package main import (
"encoding/json"
"log"
"github.com/tidwall/gjson"
) // 嵌套一个对象
type Info struct {
Age int `json:"age"`
} var info = Info{Age: 12} // 嵌套一个对象数组
type Extra struct {
Address string `json:"address"`
} // 定义需要反序列化的结构体
type UserRequest struct {
Name string `json:"userName"` // 通过tag里面的json,来指定json字符串中该字段的值从那里解析,不需要和字段名一样
NickName string `json:"nick_name"` // 如果没对应上,解析不了
info Info `json:"info"` // 小写私有的,故反序列化失效,该字段永远为空
Extra []Extra `json:"extra"`
} func main() {
jsonStr := `
{
"userName":"admin",
"nick_name":"管理员",
"info":{
"age":18
},
"extra":[
{
"address":"上海市"
},
{
"address":"北京市"
}
]
}` // 方式一:序列化成map,经常使用
anyMap := make(map[string]interface{}, 0)
if err := json.Unmarshal([]byte(jsonStr), &anyMap); err != nil {
panic(err)
}
log.Println("Unmarshal to map result:", anyMap) // 方式二:反序列化成对象,经常使用
req := UserRequest{}
if err := json.Unmarshal([]byte(jsonStr), &req); err != nil {
panic(err)
}
log.Println("Unmarshal to struct:", req) // 方式三:不反序列化,只读取单个key,经常使用。适合特别复杂的json字符串,或者有多种if else结构的场景
userName := gjson.Get(jsonStr, "userName")
nickName := gjson.Get(jsonStr, "nick_name")
age := gjson.Get(jsonStr, "info.age").Int() // 取得extra数组0位置的对象
address1 := gjson.Get(jsonStr, "extra").Array()[1]
log.Println("get raw value by key:", userName, nickName, age, address1.Get("address"))
}
运行后输出:
2022/09/13 11:09:13 Unmarshal to map result: map[extra:[map[address:上海市] map[address:北京市]] info:map[age:18] nick_name:管理员 userName:admin]
2022/09/13 11:09:13 Unmarshal to struct: {admin 管理员 {0} [{上海市} {北京市}]}
2022/09/13 11:09:13 get raw value by key: admin 管理员 18 北京市
解释
anyMap := make(map[string]interface{}, 0)
if err := json.Unmarshal([]byte(jsonStr), &anyMap);
//...
我们看到,key是string,value是interface{},所以你取值的时候,需要这样取:
ageVal,ok := anyMap["age"]
if ok{
age := ageVal.(int)
log.Println(age)
}
是不是感觉非常麻烦?一是需要判断key是否存在,二是类型转换。
所以,反序列化时这种方式不是很常用,但是序列化的时候,非常方便,用的较多。
type LoginReq struct {
UserName string `json:"user_name"`
}
func onLogin(ctx *gin.Context) {
req := LoginReq{}
if err := ctx.BindJSON(&req); err != nil {
ctx.Error(err)
}
if req.UserName == "admin" {
ctx.JSON(http.StatusOK, gin.H{"code": 0, "msg": "success"})
} else {
ctx.JSON(http.StatusUnauthorized, gin.H{"code": -1, "msg": "账号错误!"})
}
}
看到 gin.H 了吗?实际上就是:
// H is a shortcut for map[string]interface{}
type H map[string]interface{}
所以:
ctx.JSON(http.StatusOK, gin.H{"code": 0, "msg": "success”})
等价于:
ctx.JSON(http.StatusOK, map[string]interface{}{"code": 0, "msg": "success"})
这样做的好处是,不需要预先定义结构体,直接通过语法糖实现,代码更简洁。
- 字段tag中的名字要和json字符串中的对应,否则解析不到值
- 字段名不能是小写开头,私有的字段无法将被忽略,也会解析不到值
- 支持嵌套,由go标准库通过反射自动完成
userName := gjson.Get(jsonStr, "userName")
别忘记,gjson 不是标准库的包,需要使用 go get github.com/tidwall/gjson 安装。
总结
- 直接解析成 map[string]interface{}
- 解析成对象
- 读取单个key
加餐:什么是序列化?
- 客户端:发送之前,要把对象转换为二进制字节流。
- 服务器:接收到二进制流之后,要转换为对象。

go 中解析JSON的三种姿势的更多相关文章
- android中解析文件的三种方式
android中解析文件的三种方式 好久没有动手写点东西了,最近在研究android的相关技术,现在就android中解析文件的三种方式做以下总结.其主要有:SAX(Simple API fo ...
- Ajax中解析Json的两种方法
eval(); //此方法不推荐 JSON.parse(); //推荐方法 一.两种方法的区别 我们先初始化一个json格式的对象: var jsonDate = '{ "name" ...
- 解析JSON的三种方式
JSONObject JSONObject jsonObject = new JSONObject(strJson); JSONArray jsonArray = jsonObject.getJS ...
- Ajax中解析Json的两种方法详解
eval(); //此方法不推荐 JSON.parse(); //推荐方法 一.两种方法的区别 我们先初始化一个json格式的对象: var jsonDate = '{ "name&qu ...
- Java解析json数组三种情况
package com.example.demo.json; import java.util.Map; import com.alibaba.fastjson.JSON; import com.al ...
- python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)
昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...
- Golang解析json的几种方法
Golang解析json的几种方法 概要 使用Golang调用其它平台API接口时总会被多层的json串给恶心到,我记录一下自己解析json的几种方法. 一.自带的json包 func JsonUnm ...
- 解析JSON的两种方法eval()和JSON.parse()
解析JSON 一种方法是使用eval函数. var dataObj = eval("("+json+")"); 必须把文本包围在括号中,这样才能避免语法错误,迫 ...
- 问题:c# json解析;结果:c# 解析JSON的几种办法
c# 解析JSON的几种办法 欲成为海洋大师,必知晓海中每一滴水的真名. 刚开始只是想找一个转换JSON数组的方法,结果在MSDN翻到一大把. 搜索过程中免不了碰到一大堆名词:WCF => Da ...
随机推荐
- Django快速入门之项目配置
开始 环境 python:3.6.2 django:2.0.5 跑起来 用pycharm导入或新建一个Django项目,在目录中存在manage.py的文件,通过下列指令运行Django后台. pyt ...
- sql-DCL用户及权限管理及其他常用命令-mysql
查看系统信息 SHOW PROCESSLIST -- 显示哪些线程正在运行 SHOW VARIABLES -- 显示系统变量信息 SELECT now(), user(), version(); -- ...
- 史上最全学习率调整策略lr_scheduler
学习率是深度学习训练中至关重要的参数,很多时候一个合适的学习率才能发挥出模型的较大潜力.所以学习率调整策略同样至关重要,这篇博客介绍一下Pytorch中常见的学习率调整方法. import torch ...
- 坐标PCB公司,想做实时数仓、推生产线看板,和Tapdata Cloud的偶遇来得就是这么凑巧
Tapdata Cloud 是一款很有「前途」的产品.--Tapdata Cloud 用户 | 一线DBA@某PCB全球百强企业 从首次提出这一概念起,已经 10 年过去了,"工业互 ...
- 螣龙安科反入侵:EDR的缺点
EDR解决方案提供了比传统终结点安全解决方案更高的功能,并且可以增加人员数量,但是这些功能都有不少的缺点. EDR功能付出巨大代价 在过去四年中,虽然产品成本平均每年下降约35%,但即使到今天,产品的 ...
- Tomcat日志乱码解决方法
将配置文件logging.properties所有含有UTF-8的删除
- MySQL原理
MySQL基础: sql语句的执行过程: 连接器:登录连接sql数据库 分析器:分析解读sql语句,并检查是否符合SQL语法规则 优化器:对实现方式进行优化,比如在查询时决定使用哪个索引. 执行器:执 ...
- ApiDay001 __02 Java_StringBuilder
Java 核心API StringBuilder String 类型的连接性能不好,Java提供了StringBuilder解决字符串连接性能问题. 简单理解 StringBuilder性能好!(重点 ...
- PostgreSQL下的SQL Shell(psql)工具
首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485130&idx=1 ...
- RabbitMQ细说之开篇
前言 关于消息中间件的应用场景,小伙伴们应该都耳熟能详了吧,比如经常提到的削峰填谷.分布式事务.异步业务处理.大数据分析等等,分布式消息队列成为其中比较关键的桥梁,也就意味着小伙伴们得掌握相关技能:当 ...