【Golang 接口自动化04】 解析接口返回JSON串

chatgpt/2023/10/4 8:54:40

目录

前言

解析到结构体

json数据与struct字段是如何相匹配的呢?

解析到interface

Go类型和JSON类型

实例代码

simpleJson

总结

资料获取方法


前言

上一次我们一起学习了如何解析接口返回的XML数据,这一次我们一起来学习JSON的解析方法。

JSON(Javascript Object Notation)是一种轻量级的数据交换语言,以文字为基础,具有自我描述性且易于让人阅读。XML是一个完整的标记语言,而JSON不是。JSON比XML更小、更快,更易解析,因此其被广泛应用于网络数据传输领域。

Go语言的标准库已经非常好的支持了JSON,可以很容易的对JSON数据进行编、解码的工作。下面我们通过一些实例一起来学习。

首先我们假设我们的接口返回的JSON数据如下:

{   "code": "00","message": "SUCCESS","describe": "成功","resultInfo": { "uniqueNumber": "201808161133401673324075025000035" } 
}

解析到结构体

这种方式与xml解析的方法基本没有什么区别,我们首先要定义一个结构体,然后调用json.Unmarshal把数据解析到结构体:

func StructMethod() {resp := `{"code": "00","message": "SUCCESS","describe": "成功","resultInfo": { "uniqueNumber": "201808161133401673324075025000035" } }`type JsonResp struct {Code       int               `json:"code"`Message    string            `json:"message"`Describe   string            `json:"describe"`ResultInfo map[string]string `json:"resultInfo"`}var smsresp JsonResptemp := []byte(resp)errs := json.Unmarshal(temp, &smsresp)if errs != nil {return}fmt.Println(smsresp.Code)fmt.Println(smsresp.Describe)fmt.Println(smsresp.Message)fmt.Println(smsresp.ResultInfo["uniqueNumber"])
}

json数据与struct字段是如何相匹配的呢?

可能有的小伙伴和我一样好奇,在解析的时候,json数据与struct字段是如何相匹配的呢?例如JSON的key是code,那么怎么找对应的字段呢?

  • 首先查找tag含有code的可导出的struct字段(首字母大写)
  • 其次查找字段名是code的导出字段
  • 最后查找类似Code或者COde这样的除了首字母之外其他大小写不敏感的导出字段

注意: 能够被赋值的字段必须是可导出字段(即首字母大写)。同时JSON解析的时候只会解析能找得到的字段,找不到的字段会被忽略。我们在实际使用的过程中一定要随时警惕这一点。

其实与这个潜在的坑相比,它的优势非常明显:当你接收到一个很大的JSON数据结构而你却只想获取其中的部分数据的时候,你只需将你想要的数据对应的字段名大写,即可轻松解决。

解析到interface

上面那种解析方式是在我们知晓被解析的JSON数据的结构的前提下采取的方案,如果我们不知道被解析的数据的格式,又应该如何来解析呢?

Go类型和JSON类型

我们知道interface{}可以用来存储任意数据类型的对象,这种数据结构正好用于存储解析的未知结构的json数据的结果。JSON包中采用map[string]interface{}和[]interface{}结构来存储任意的JSON对象和数组。Go类型和JSON类型的对应关系如下:

类型JSON类型
boolJSON booleans,
float64JSON numbers,
stringJSON strings,
nilJSON null.

实例代码

// InterfaceMethod 方式
func InterfaceMethod() {resp := `{"code": "00","message": "SUCCESS","describe": "成功","resultInfo": {"uniqueNumber": "201808161133401673324075025000035"} }`var x interface{}_ = json.Unmarshal([]byte(resp), &x)m := x.(map[string]interface{})for k, v := range m {switch vv := v.(type) {case string:fmt.Println(k, "is string", vv)case int:fmt.Println(k, "is int", vv)case float64:fmt.Println(k, "is float64", vv)case []interface{}:fmt.Println(k, "is an array:")for i, u := range vv {fmt.Println(i, u)}case map[string]interface{}:fmt.Println(k, "is an map[string]string:")for i, u := range vv {fmt.Println(i, u)}default:fmt.Println(k, "is of a type didn't handle")}}
}

simpleJson

上面两种方式其实已经能应付我们一般的工作了,但是单纯就解析数据而言(这里先买个关子),其实还有一种更简单的方式,那就是第三方库:github.com/bitly/go-simplejson,使用方法如下:

func SimplejsonMethod() {resp := `{"code": "00","message": "SUCCESS","describe": "成功","resultInfo": { "uniqueNumber": "201808161133401673324075025000035" } }`js, errs := NewJson([]byte(resp))if errs != nil {return}discount := js.Get("resultInfo").Get("uniqueNumber")strcode, _ := js.Get("code").String()intcode, _ := js.Get("code").Int()path := js.GetPath("resultInfo", "uniqueNumber")fmt.Println(discount)fmt.Println(strcode)fmt.Println(intcode)fmt.Println(path)
}

运行输出:

bingo@Mac unpackData$ go run JSONparse.go
&{201808161133401673324075025000035}
00
0
&{201808161133401673324075025000035}

GetPath方法是Get的人精简版,使用结尾调用的方法可以吧输出的结果转化为指定的类型(string 00 转换为 0 )。

那么多个方法的调用怎么完成数据传递的呢?输出结果的&符号其实已经暴露了它的身份,对就是指针,这个库每个方法接收和返回的都是指针数据。

总结

  • json 解析 到struct
  • interface{}与type assert的配合使用
  • simplejson
  • 学习一门语言是一个慢慢熟悉的过程,初始是不易使用完成度太高的轮子

资料获取方法

【留言777】

各位想获取源码等教程资料的朋友请点赞 + 评论 + 收藏,三连!

三连之后我会在评论区挨个私信发给你们~

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

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

Vue实现表单本地草稿功能

背景 最近做了一个Lesson Learned系统,在业务功能都完成之后,用户反响很强烈,要求实现一个草稿功能,因为表单比较大,他们怕在工作的时候,突然有什么事情耽搁,导致系统被关闭,这时候…

【华为OD】运维日志排序

题目描述: 运维工程师采集到某产品线网运行一天产生的日志n条,现需根据日志时间先后顺序对日志进行排序,日志时间格式为H:M:S.N。 H表示小时(0~23) M表示分钟(0~59) S表示秒(0~59) N表示毫秒(0~999) 时间可能并没有补全,也就是说&…

产品经理:如何做好项目需求管理

产品经理每天都要接触各种不同的需求,只有对这些需求进行分析,才能更好地了解问题,从而制定相应的解决方案。那么,怎么做需求分析呢? 一、需求确定 选择需求是很重要的,先做出选择,才会有对应的…

Games101学习笔记 - 变换矩阵基础

二维空间下的变换 缩放矩阵 缩放变换: 假如一个点(X,Y)。x经过n倍缩放,y经过m倍缩放,得到的新点(X1,Y1);那么新点和远点有如下关系,X1 n*X, Y1 m*Y写成矩阵就是如下…

Linux vi/vim以及三种模式常用快捷键

vi/vim vi和vimvi 命令模式vi 插入模式vi 底行模式 vi和vim vi 和 vim 都是在 Linux 系统中的文本编辑器。vim 实际上是 vi 的增强版,提供了更多的功能和改进。 vi: vi 是一个经典的文本编辑器,几乎在每个 Linux 发行版中都预装了。vi 的使用…

adb shell使用总结

文章目录 日志记录系统概览adb 使用方式 adb命令日志过滤按照告警等级进行过滤按照tag进行过滤根据告警等级和tag进行联合过滤屏蔽系统和其他App干扰,仅仅关注App自身日志 查看“当前页面”Activity文件传输截屏和录屏安装、卸载App启动activity其他 日志记录系统概…

java - 代码块

代码块 基本介绍 代码块又称为初始化块,属于类中的成员,即类的一部分,和方法类似。将逻辑语句封装在方法体中,通过{}包围起来。 但和方法不同,没有方法名、没有返回、没有参数。只有方法体,而且不用通过…

Sestra 实用教程(三)输入与输出

目 录 一、前言二、分析流程三、输入文件3.1 模型与荷载3.2 分析控制数据 四、输出文件五、参考文献 一、前言 SESAM (Super Element Structure Analysis Module)是由挪威船级社(DNV-GL)开发的一款有限元分析(FEA&…
推荐文章