前言

上一次我们一起学习了如何解析接口返回的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 JsonResp
temp := []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类型
bool JSON booleans,
float64 JSON numbers,
string JSON strings,
nil JSON 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
  • 学习一门语言是一个慢慢熟悉的过程,初始是不易使用完成度太高的轮子

【Golang 接口自动化04】 解析接口返回JSON串的更多相关文章

  1. spring入门(七)【springMVC返回json串】

    现在多数的应用为了提高交互性多使用异步刷新,即在不刷新整个页面的情况下,只刷新局部,局部刷新用得最多就是ajax,ajax和后台进行交互的数据格式使用的最多的是JSON,这里简单描述,在springm ...

  2. Python3.x:访问带参数链接并且获取返回json串

    Python3.x:访问带参数链接并且获取返回json串 示例一: import json import xml.dom.minidom from urllib import request, par ...

  3. springmvc 1.接受日期类型的参数 2.后台返回json串的格式处理(返回json串null值处理为"")

    springmvc中的配置: <bean id="dateConvert" class="com.iomp.util.DateConvert"/> ...

  4. python接口自动化(十九)--Json 数据处理---实战(详解)

    简介 上一篇说了关于json数据处理,是为了断言方便,这篇就带各位小伙伴实战一下.首先捋一下思路,然后根据思路一步一步的去实现和实战,不要一开始就盲目的动手和无头苍蝇一样到处乱撞,撞得头破血流后而放弃 ...

  5. python接口自动化24-有token的接口项目使用unittest框架设计

    获取token 在做接口自动化的时候,经常会遇到多个用例需要用同一个参数token,并且这些测试用例跨.py脚本了. 一般token只需要获取一次就行了,然后其它使用unittest框架的测试用例全部 ...

  6. python接口自动化根据请求接口类型进行封装

    根据不同的请求类型(GET/POST)进行接口请求封装 import requests import json class RunMain: def __init__(self, url, metho ...

  7. spring 4.x下让http请求返回json串

    当前很多应用已经开始将响应返回为json串,所以基于springframework框架开发的服务端程序,让响应返回json字符串成为了一种常用手段. 这里介绍一下如何在spring-MVC框架下方便快 ...

  8. 接口自动化(三)--读取json文件中的数据

    上篇讲到实际的请求数据放置在json文件内,这一部分记述一下python读取json文件的实现. 代码如下(代码做了简化,根据需要调优:可做一些容错处理): 1 import json 2 3 cla ...

  9. python接口自动化:响应内容中json字符串对象的处理

    实现代码如下: import json #定义一个字典.一个列表.两个字符串({}中必须是双引号) di1={"} di2=[{"}] di3='{"name" ...

随机推荐

  1. Qt实现 QQ好友列表QToolBox

    简述 QToolBox类提供了一个列(选项卡式的)部件条目. QToolBox可以在一个tab列上显示另外一个,并且当前的item显示在当前的tab下面.每个tab都在tab列中有一个索引位置.tab ...

  2. Atcoder Tenka1 Programmer Contest 2019 E - Polynomial Divisors

    题意: 给出一个多项式,问有多少个质数\(p\)使得\(p\;|\;f(x)\),不管\(x\)取何值 思路: 首先所有系数的\(gcd\)的质因子都是可以的. 再考虑一个结论,如果在\(\bmod ...

  3. Azkaban-开源任务调度程序(使用篇)

    上篇文章说到了安装,这次说说使用 登录 https://localhost:8443 注意是https,采用的是jetty ssl链接.输入账号密码azkaban/azkanban(如果你之前没有更改 ...

  4. bzoj1056/1862 [Zjoi2006]GameZ游戏排名系统

    题目链接:1,2 treap恶心题,不多说 #include<algorithm> #include<iostream> #include<cstdlib> #in ...

  5. MySQL数据库----表与表之间的关系

    表1 foreign key 表2 则表1的多条记录对应表2的一条记录,即多对一 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以对应表2的一条记录 ...

  6. MySQL中的基本SQL语句

    标准SQL包含了4种基本的语句类别: DDL语句,数据定义语句,主要用来定义数据库,表名,字段,例如create,drop,alter. DML语句,数据操作语句,用来对数据记录的增删改查,还用来保证 ...

  7. Python descriptor 以及 内置property()函数

    Python Descriptor  1, Python Descriptor是这样一个对象 它按照descriptor协议, 有这样的属性之一 def __get__(self, obj, type ...

  8. 20145303刘俊谦《网络攻防》Exp4 Msf基础

    20145303刘俊谦<网络攻防>Exp4 Msf基础 实验目标 • 掌握metasploit的基本应用方式,掌握常用的三种攻击方式的思路. • 一个主动攻击,如ms08_067: • 一 ...

  9. 微信小程序——3、逻辑js文件

    逻辑层js文件 微信小程序前端进行了层次划分,分为逻辑层和视图层.逻辑层实现对数据的加工和处理.与HTML页面相似,逻辑层使用JavaScript编写.逻辑层将数据处理后发送至视图层,同时接受视图层的 ...

  10. C++ 细小知识点

    1. C++ 拷贝构造函数参数为const类型 原因:因为复制构造函数是用引用方式传递复制对象,引用方式传递的是地址,因此在构造函数内对该引用的修改会影响源对象,防止源对象被修改,就要把参数类型设为c ...