Golang实践录:gin绑定解析json的两种方法

本文介绍 Golang 的 gin 框架接收json数据并解析的2种方法。

起因及排查

某微服务工程,最近测试发现请求超时,由于特殊原因超时较短,如果请求处理耗时超过1秒则认为失败。排查发现,可能是gin接收解析json数据存在耗时,代码使用ctx.ShouldBindJSON直接解析得到所需结构体,然后通过自实现的FormatJsonStruct函数格式化并输出到日志。该格式函数如下:

func FormatJsonStruct(str interface{}, format bool) (ret string) {ret = ""jsonstr, err := json.Marshal(str)if err != nil {return}if format {var out bytes.Buffer_ = json.Indent(&out, []byte(jsonstr), "", "    ")ret = out.String()} else {ret = string(jsonstr)}return
}

从上述过程看到,先是调用了ShouldBindJSON,再调用了Marshal函数解析成字符串。于是考虑调用ReadAll读取数据,再用Unmarshal解析成结构体,直接输出结构体数据。下面模拟2种不同的解析josn方法。

模拟程序

本节结合代码,简单描述模拟程序。详见文附录。

一般地,在gin中,业务处理函数带有*gin.Context参数,如本文的HandleGinShouldBindJSON,使用ctx.ShouldBindJSON(&request)ctx中带的数据直接转换成目标结构体。

也可以通过ioutil.ReadAll(ctx.Request.Body)先读取客户端来的数据,由于约定为json格式数据,所以可以用json.Unmarshal解析成结构体。

无法哪种方法,其实都很方便,相对而言,前者更便捷。

测试结果

使用curl模拟请求命令,示例如下:

curl http://127.0.0.1:9000/foo -X POST -H "Content-Type:application/json" -d  '{"id":"test_001", "op":"etc", "timestamp":12342134341234, "data":{"name":"foo", "addr":"bar", "code":450481, "age":100}}'curl http://127.0.0.1:9000/bar -X POST -H "Content-Type:application/json" -d  '{"id":"test_001", "op":"etc", "timestamp":12342134341234, "data":{"name":"foo", "addr":"bar", "code":450481, "age":100}}'

服务端输出日志:

=== RUN   TestGin
test of gin
run gin
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.        - using env:   export GIN_MODE=release- using code:  gin.SetMode(gin.ReleaseMode)[GIN-debug] POST   /foo                      --> webdemo/test/gin_test.HandleGinShouldBindJSON (1 handlers)
[GIN-debug] POST   /bar                      --> webdemo/test/gin_test.HandleGinUnmarshal (1 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :9000
ShouldBindJSON: request: #{test_001 etc 12342134341234 {foo bar 450481 100}}
Unmarshal request: #{test_001 etc 12342134341234 {foo bar 450481 100}}
exit status 0xc000013a

小结

就目前测试和修改结果看,本文所述方法并非主因,真正原因待查。

完整代码

/*
结构体
{"id": "test_001","op": "etc","timestamp": 12342134341234,"data": {"name": "foo","addr": "bar","code": 450481,"age": 100}
}curl http://127.0.0.1:9000/foo -X POST -H "Content-Type:application/json" -d  '{"id":"test_001", "op":"etc", "timestamp":12342134341234, "data":{"name":"foo", "addr":"bar", "code":450481, "age":100}}'curl http://127.0.0.1:9000/bar -X POST -H "Content-Type:application/json" -d  '{"id":"test_001", "op":"etc", "timestamp":12342134341234, "data":{"name":"foo", "addr":"bar", "code":450481, "age":100}}'*/package testimport ("encoding/json""fmt""io/ioutil""strings""testing""github.com/gin-gonic/gin"
)var g_port string = "9000"type MyRequest_t struct {Id        string    `json:"id"`Op        string    `json:"op"`Timestamp int       `json:"timestamp"`Data      ReqData_t `json:"data"`
}type ReqData_t struct {Name string `json:"name"`Addr string `json:"addr"`Code int    `json:"code"`Age  int    `json:"age"`
}func routerPost(r *gin.Engine) {r.POST("/foo", HandleGinShouldBindJSON)r.POST("/bar", HandleGinUnmarshal)
}func initGin() {fmt.Println("run gin")router := gin.New()routerPost(router)router.Run(":" + g_port)
}func HandleGinShouldBindJSON(ctx *gin.Context) {var request MyRequest_tvar err errorctxType := ctx.Request.Header.Get("Content-Type")if strings.Contains(ctxType, "application/json") { // 纯 json// 先获取总的jsonif err = ctx.ShouldBindJSON(&request); err != nil {fmt.Printf("ShouldBindJSON failed: %v\n", err)return}fmt.Printf("ShouldBindJSON: request: #%v\n", request)} else {fmt.Println("非json")return}
}func HandleGinUnmarshal(ctx *gin.Context) {var request MyRequest_tvar err errorvar reqbuffer []bytectxType := ctx.Request.Header.Get("Content-Type")if strings.Contains(ctxType, "application/json") { // 纯 jsonreqbuffer, err = ioutil.ReadAll(ctx.Request.Body)if err != nil {fmt.Printf("ReadAll body failed: %v\n", err)return}err = json.Unmarshal(reqbuffer, &request)if err != nil {fmt.Printf("Unmarshal to request failed: %v\n", err)return}fmt.Printf("Unmarshal request: #%v\n", request)} else {fmt.Println("非json")return}
}func TestGin(t *testing.T) {fmt.Println("test of gin")initGin()
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/237697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据---34.HBase数据结构

一、HBase简介 HBase是一个开源的、分布式的、版本化的NoSQL数据库(即非关系型数据库),依托Hadoop分布式文件系统HDFS提供分布式数据存储,利用MapReduce来处理海量数据,用Zookeeper作为其分布式协同服务,一…

逆波兰计算器的完整代码

前置知识&#xff1a; 将中缀表达式转为List方法&#xff1a; //将一个中缀表达式转成中缀表达式的List//即&#xff1a;(3042)*5-6 》[(, 30, , 42, ), *, 5, -, 6]public static List<String> toIndixExpressionList(String s) {//定义一个List&#xff0c;存放中缀表达…

R语言——基本操作(二)

目录 一、矩阵与数组 二、列表 三、数据框 四、因子 五、缺失数据 六、字符串 七、日期和时间 参考 一、矩阵与数组 matrix&#xff1a;创建矩阵&#xff0c;nrow 和 ncol 可以省略&#xff0c;但其值必须满足分配条件&#xff0c;否则会报错 只写一个值则自动分配&…

5. 创建型模式 - 单例模式

亦称&#xff1a; 单件模式、Singleton 意图 单例模式是一种创建型设计模式&#xff0c; 让你能够保证一个类只有一个实例&#xff0c; 并提供一个访问该实例的全局节点。 问题 单例模式同时解决了两个问题&#xff0c; 所以违反了单一职责原则&#xff1a; 保证一个类只有一…

人工智能在现代科技中的应用和未来发展趋势。

&#x1f431; 个人主页&#xff1a;SHOW科技&#xff0c;公众号&#xff1a;SHOW科技 &#x1f64b;‍♂️ 作者简介&#xff1a;2020参加工作&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab;优质专栏&#x…

xtu oj 1394 单调

单调 题目描述 n∑ki0ai⋅bi,b≥2&#xff0c;如果i>0时&#xff0c;ai>ai−1&#xff0c;那么我们称这个数n是在b进制下是单调的。比如6,在3进制下为20(3)&#xff0c;所以6在3进制下是单调的。现在已知n&#xff0c;求最小的基b&#xff0c;使得n是单调的。 输入 第一…

谷歌Gemini造假始末

&#x1f4a1;大家好&#xff0c;我是可夫小子&#xff0c;《小白玩转ChatGPT》专栏作者&#xff0c;关注AIGC、读书和自媒体。 在过去一年中&#xff0c;OpenAI ChatGPT引发了一股AI新浪潮&#xff0c;而谷歌则一直处于被压制的状态&#xff0c;迫切需要一款现象级的AI产品来…

计算机网络:应用层

0 本节主要内容 问题描述 解决思路 1 问题描述 不同的网络服务&#xff1a; DNS&#xff1a;用来把人们使用的机器名字&#xff08;域名&#xff09;转换为 IP 地址&#xff1b;DHCP&#xff1a;允许一台计算机加入网络和获取 IP 地址&#xff0c;而不用手工配置&#xff1…

MySQL中MVCC的流程

参考文章一 参考文章二 当谈到数据库的并发控制时&#xff0c;多版本并发控制&#xff08;MVCC&#xff09;是一个重要的概念。MVCC 是一种用于实现数据库事务隔离性的技术&#xff0c;常见于像 PostgreSQL 和 Oracle 这样的数据库系统中。 MVCC 的核心思想是为每个数据行维护…

kali-钓鱼网站远程代码漏洞分析

文章目录 一、靶场搭建二、开始信息收集&#xff0c;寻找漏洞三、使用蚁剑连接后门程序四、使用webshell查看数据库信息五、进入网站后台 实验环境 Kali CentOs 一、靶场搭建 CentOsIP地址192.168.64.159 #关闭centos防火墙 [rootlocalhost ~]# systemctl disable --now fi…

JavaWeb笔记之WEB开发

一、引言 1.1 C/S和B/S C/S和B/S是软件发展过程中出现的两种软件架构方式。 1.2 C/S架构 &#xff08;Client/Server 客户端/服务器&#xff09;。 特点&#xff1a;必须在客户端安装特定软件。 优点&#xff1a;图形效果显示较好(如&#xff1a;3D游戏)。 缺点&#xff1…

jQuery、vue、小程序、uni-app中的本地存储数据和接受数据

jQuery: 存储数据&#xff1a; // 存储数据到本地 localStorage.setItem(key, value);// 存储对象到本地 localStorage.setItem(key, JSON.stringify(object));获取数据&#xff1a; // 从本地获取数据 var value localStorage.getItem(key);// 从本地获取对象 var object …

2023秋季学期数据库原理重修相关复习总结知识点

使用 ALTER TABLE 命令可以修改表结构&#xff0c;其中包括设置字段的默认值。使用 LIKE 关键字进行模糊查询&#xff0c;通常结合 % 或其他通配符使用。表的关联使用 JOIN 关键字。使用 LIMIT 子句限制查询结果的行数&#xff0c;实现分页效果。使用 DATE() 函数对日期进行格式…

【Java代码审计】RCE篇

【Java代码审计】RCE篇 1.Java中的RCE2.ProcessBuilder命令执行漏洞3.Runtime exec命令执行漏洞4.脚本引擎代码注入5.RCE的防御 1.Java中的RCE 在PHP开发语言中有system()、exec()、shell_exec()、eval()、passthru()等函数可以执行系统命令。在Java开发语言中可以执行系统命令…

C#使用HTTP方式对接WebService

C#使用HTTP方式对接WebService C#对接WebService的几种方式 1.直接引用服务 添加服务 添加成功后, 会显示服务详细 调用服务 使用HTTPPost调用WebService option.RequestDataStr GetHttpRequestXml(strXmlBody); // 创建一个 HttpClient 对象 using (HttpClient client …

《深入浅出SSD》:固态存储核心技术、原理与实战

目录 前言 内容简介 作者简介 名人推荐 本书目录 了解更多 结语 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊《深入浅出SSD》这本书&#xff0c;希望大家能觉得实用&#xff01; 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&…

shell脚本发送钉钉告警通知案例一则 —— 筑梦之路

实现原理 将要发送的消息内容保存到json文件中&#xff0c;通过curl命令请求钉钉机器人接口。 脚本示例 cat /opt/disk_usage_check.sh #!/bin/bash# 设置警告阈值 THRESHOLD80# CURRENT_TIME$(date "%Y-%m-%d %H:%M:%S") # 获取主机名和IP HOSTNAME$(hostname) I…

助力智能车辆检测计数,基于官方YOLOv8全系列[n/s/m/l/x]开发构建道路交通场景下不同参数量级车流检测计数系统

在很多道路交通卡口都有对车流量的统计计算需要&#xff0c;有时候一些特殊时段、特殊节日等时间下对于车流的监测预警更为重要&#xff0c;恶劣特殊天气下的提早监测、预警、限流对于保证乘客、驾驶员的安全是非常重要的措施&#xff0c;本文的主要目的就是想要开发构建道路交…

2 Pandas之Series

Pandas数据结构简介 Pandas可以处理以下三种数据&#xff1a; SeriesDataFramePanel 这些数据建立在NumPy上&#xff0c;故可以快速运行。 纬度描述 更好的理解这些数据结构的方式是将高维数据看作是低维数据的容器。例如&#xff0c;DataFrame是Series的容器&#xff0c;P…

最新ChatGPT网站系统源码+AI绘画系统+支持GPT语音对话+详细图文搭建教程/支持GPT4.0/H5端系统/文档知识库

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Ch…