zoukankan      html  css  js  c++  java
  • 【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
    • 学习一门语言是一个慢慢熟悉的过程,初始是不易使用完成度太高的轮子
  • 相关阅读:
    Some Depth Theory
    Hom和$otimes$如何把我绕晕
    A natrual way to introduce homotopy groups
    指数多项式的Galois群计算
    Trianglated Category and Derived Categories
    最近的代数课上的一些灵魂提问
    致青年朋友的一封信 莫洛亚
    一个函数证明题
    游客的故事
    14. 运算符重载(二)
  • 原文地址:https://www.cnblogs.com/Detector/p/9048678.html
Copyright © 2011-2022 走看看