【Golang 接口自动化04】 解析接口返回JSON串
前言
上一次我们一起学习了如何解析接口返回的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串的更多相关文章
- spring入门(七)【springMVC返回json串】
		
现在多数的应用为了提高交互性多使用异步刷新,即在不刷新整个页面的情况下,只刷新局部,局部刷新用得最多就是ajax,ajax和后台进行交互的数据格式使用的最多的是JSON,这里简单描述,在springm ...
 - Python3.x:访问带参数链接并且获取返回json串
		
Python3.x:访问带参数链接并且获取返回json串 示例一: import json import xml.dom.minidom from urllib import request, par ...
 - springmvc 1.接受日期类型的参数 2.后台返回json串的格式处理(返回json串null值处理为"")
		
springmvc中的配置: <bean id="dateConvert" class="com.iomp.util.DateConvert"/> ...
 - python接口自动化(十九)--Json 数据处理---实战(详解)
		
简介 上一篇说了关于json数据处理,是为了断言方便,这篇就带各位小伙伴实战一下.首先捋一下思路,然后根据思路一步一步的去实现和实战,不要一开始就盲目的动手和无头苍蝇一样到处乱撞,撞得头破血流后而放弃 ...
 - python接口自动化24-有token的接口项目使用unittest框架设计
		
获取token 在做接口自动化的时候,经常会遇到多个用例需要用同一个参数token,并且这些测试用例跨.py脚本了. 一般token只需要获取一次就行了,然后其它使用unittest框架的测试用例全部 ...
 - python接口自动化根据请求接口类型进行封装
		
根据不同的请求类型(GET/POST)进行接口请求封装 import requests import json class RunMain: def __init__(self, url, metho ...
 - spring 4.x下让http请求返回json串
		
当前很多应用已经开始将响应返回为json串,所以基于springframework框架开发的服务端程序,让响应返回json字符串成为了一种常用手段. 这里介绍一下如何在spring-MVC框架下方便快 ...
 - 接口自动化(三)--读取json文件中的数据
		
上篇讲到实际的请求数据放置在json文件内,这一部分记述一下python读取json文件的实现. 代码如下(代码做了简化,根据需要调优:可做一些容错处理): 1 import json 2 3 cla ...
 - python接口自动化:响应内容中json字符串对象的处理
		
实现代码如下: import json #定义一个字典.一个列表.两个字符串({}中必须是双引号) di1={"} di2=[{"}] di3='{"name" ...
 
随机推荐
- mybitis学习笔记
			
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-// ...
 - 按照用户名和角色查询用户liferay
			
需求:当登录的用户输入用户的名字和角色的时候,模糊查询,然后就是Ajax的异步请求刷新界面 首先在一个工具类中写上一条你要写的sql语句代码如下: package com.ebizwindow.crm ...
 - Mybatis—三剑客之generator使用方法
			
三剑客之generator主要用于自动生成POJO实体类 准备素材: mybatis-generator-core-1.3.2.jar mysql-connector-java-5.1.2 ...
 - 把HDFS上的数据导入到Hive中
			
1. 首先下载测试数据,数据也可以创建 http://files.grouplens.org/datasets/movielens/ml-latest-small.zip 2. 数据类型与字段名称 m ...
 - java后台获取和js拼接展示信息
			
java后台获取和js拼接展示信息: html页面代码: <div class="results-bd"> <table id="activityInf ...
 - Linux基础命令---cmp
			
cmp 用字节的方式,比较两个文件是否存在差异,但是不保存运算结果.Cmp指令只会根据结果设置相关的标志位,这个指令之后往往会跟着一个条件跳转指令. 此命令的适用范围:RedHat.RHEL.Ubun ...
 - centos  infiniband网卡安装配置
			
硬件:Mellanox InfiniBand,主要包括 HCA(主机通道适配器)和交换机两部分 软件:CentOS 6.4 MLNX_OFED_LINUX-2.1-1.0.0-rhel6.4-x86_ ...
 - 一起来全面解析5G网络领域最关键的十大技术
			
提到5G,很多人的第一印象就是它的网络速度快.延时性低.带宽大,没错,这就是5G时代的特点!5G作为第五代移动通信网络,其峰值理论传输速度可达每秒数十Gb,这比4G网络的传输速度快数百倍,整部超高画质 ...
 - live555 编译
			
项目里面需要简单的rtsp服务器来实现视频预览等功能: rtsp本来不是太复杂的东西,github上有很多功能都比较完善的项目可以随便拿来用,但是测试过程中发现live555还是有性能上的一些差异: ...
 - Python3 判断文件和文件夹是否存在、创建文件夹
			
Python3 判断文件和文件夹是否存在.创建文件夹 python中对文件.文件夹的操作需要涉及到os模块和shutil模块. 创建文件: 1) os.mknod(“test.txt”) 创建空文件 ...