jck28-lucio-多层嵌套响应断言

目录

  • 多层嵌套响应介绍
  • JSONPath 语法
  • JSONPath 使用

课程目标

  1. 掌握从多层嵌套响应体的中提取字段。
  2. 掌握 JSONPath 的语法知识。
  3. 掌握如何对复杂的 JSON 类型的响应体完成断言。

思考

如果要从一个非常复杂的 json 结构中,提取数据信息,你通常是怎么提取的?

多层嵌套结构

// - 层级多。
// - 嵌套关系复杂。
{
  "errcode": 0,
  "errmsg": "ok",
  "userid": "zhangsan",
  "name": "张三",
  "department": [1, 2],
  "order": [1, 2],
  "position": "后台工程师",
  "mobile": "13800000000",
  "gender": "1",
  "email": "zhangsan@gzdev.com",
  "biz_mail": "zhangsan@qyycs2.wecom.work",
  "is_leader_in_dept": [1, 0],
  "direct_leader": ["lisi", "wangwu"],
  "avatar": "http://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0",
  "thumb_avatar": "http://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/100",
  "telephone": "020-123456",
  "alias": "jackzhang",
  "address": "广州市海珠区新港中路",
  "open_userid": "xxxxxx",
  "main_department": 1,
  "extattr": {
    "attrs": [
      {
        "type": 0,
        "name": "文本名称",
        "text": {
          "value": "文本"
        }
      },
      {
        "type": 1,
        "name": "网页名称",
        "web": {
          "url": "http://www.test.com",
          "title": "标题"
        }
      }
    ]
  },
  "status": 1,
  "qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx",
  "external_position": "产品经理",
  "external_profile": {
    "external_corp_name": "企业简称",
    "wechat_channels": {
      "nickname": "视频号名称",
      "status": 1
    },
    "external_attr": [
      {
        "type": 0,
        "name": "文本名称",
        "text": {
          "value": "文本"
        }
      },
      {
        "type": 1,
        "name": "网页名称",
        "web": {
          "url": "http://www.test.com",
          "title": "标题"
        }
      },
      {
        "type": 2,
        "name": "测试app",
        "miniprogram": {
          "appid": "wx8bd80126147dFAKE",
          "pagepath": "/index",
          "title": "my miniprogram"
        }
      }
    ]
  }
}

## 多层嵌套结构字段提取
场景	方式
提取 errcode 对应的值	res["errcode"]
提取 title 对应的值	res["extattr"]["external_profile"]["external_attr"][1]["web"]["title"]
提取 type 为 0 的 name	编码实现
提取 attrs 下的所有的 name	编码实现
![image|800x246](upload://wbgp5Up9FPVLWyr7PFV241Muj60.jpeg)


##  JSONPath 简介
在 JSON 数据中定位和提取特定信息的查询语言。
JSONPath 使用类似于 XPath 的语法,使用路径表达式从 JSON 数据中选择和提取数据。
相比于传统的提取方式,更加灵活,并且支持定制化。

## JSONPath 对比
场景	对应实现	JSONPath 实现
提取 errcode 对应的值	res["errcode"]	$.errcode
提取 title 对应的值	res["extattr"]["external_profile"]["external_attr"][1]["web"]["title"] 等	$..title
提取 type 为 0 的 name	编码实现	$..external_attr[?(@.type==0)].name
提取 attrs 下的所有的 name	编码实现	$..attrs..name
![image|800x315](upload://eFzz2RWQGTVro6nFv3GUKq3UZrh.jpeg)


## JSONPath 如何使用
语法知识。
第三方库调用。

## JSONPath 语法
符号	描述
$	查询的根节点对象,用于表示一个 json 数据,可以是数组或对象
@	过滤器(filter predicate)处理的当前节点对象
*	通配符
.	获取子节点
..	递归搜索,筛选所有符合条件的节点
?()	过滤器表达式,筛选操作
[start:end]	数组片段,区间为[start,end),不包含 end
[A]或[A,B]	迭代器下标,表示一个或多个数组下标
![image|800x365](upload://iq2Prk739eO4CQcslmREQb5iknb.jpeg)

## JSONPath 的练习环境
https://jsonpath.hogwarts.ceshiren.com/

{
“store”: {
“book”: [
{
“category”: “reference”,
“author”: “Nigel Rees”,
“title”: “Sayings of the Century”,
“price”: 8.95
},
{
“category”: “fiction”,
“author”: “Evelyn Waugh”,
“title”: “Sword of Honour”,
“price”: 12.99
},
{
“category”: “fiction”,
“author”: “Herman Melville”,
“title”: “Moby Dick”,
“isbn”: “0-553-21311-3”,
“price”: 8.99
},
{
“category”: “fiction”,
“author”: “J. R. R. Tolkien”,
“title”: “The Lord of the Rings”,
“isbn”: “0-395-19395-8”,
“price”: 22.99
}
],
“bicycle”: {
“color”: “red”,
“price”: 19.95
}
},
“expensive”: 10
}


## JSONPath 练习题目
获取所有书籍的作者
获取所有作者
获取 store 下面的所有内容
获取所有的价格
获取第三本书
获取所有包含 isbn 的书籍
获取所有价格小于 10 的书
获取所有书籍的数量

## JSONPath 练习
需求	JsonPath
所有书籍的作者	$.store.book[*].author
所有作者	$..author
store 下面的所有内容	$.store.*
所有的价格	$.store..price
第三本书	$..book[2]
所有包含 isbn 的书籍	$..book[?(@.isbn)]
所有价格小于 10 的书	$.store.book[?(@.price < 10)]
所有书籍的数量	$..book.length
![image|721x418](upload://xHuNq4zcqUnDTWYjlWdN5QQJhPC.jpeg)


## JSONPath 与代码结合(Python)
环境安装:pip install jsonpath

具体的使用。
jsonpath.jsonpath(源数据对象, jsonpath表达式)

## JSONPath 与代码结合(Java)
2.8.0 com.jayway.jsonpath json-path ${json-path.version}

public class TestJsonpath {
@Test
void jsonpathRes(){
String jsonData = “{"username":"hogwarts","password":"test12345","code":""}”;
String res = given()
.body(jsonData)
.when()
.post(“https://httpbin.hogwarts.ceshiren.com/post”)
.then()
.extract().response().getBody().asString();
// 第一种获取方式
DocumentContext context = JsonPath.parse(res);
ArrayList codeList = context.read(“$…code”);
// 第二种获取方式
// ArrayList codeList2 = JsonPath.read(res, “$…code”);
}
}

## 总结
源码地址(Java)
[点击查看演示源码地址](http://gitlab.stuq.ceshiren.com)

## 附录:完整依赖配置
UTF-8 11 5.9.2 3.11.0 3.0.0 5.3.0 2.8.0 2.21.0 1.9.19 2.12.0 https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline org.junit junit-bom ${junit.jupiter.version} pom import
<!--        junit 相关依赖下载-->
<!-- junit5 -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <scope>test</scope>
</dependency>
<!-- junit5-suite -->
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-suite</artifactId>
    <scope>test</scope>
</dependency>
<!-- 用做兼容老版本 -->
<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
</dependency>
<!-- rest-assured -->
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>${rest-assured.version}</version>
    <scope>compile</scope>
</dependency>
<!-- json path 解析json文件 -->
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>${json-path.version}</version>
</dependency>
<!--        allure报告-->
<dependency>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-junit5</artifactId>
    <version>${allure.version}</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>${aspectj.version}</version>
</dependency>
org.apache.maven.plugins maven-surefire-plugin ${maven-surefire-plugin.version} -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" org.junit.jupiter junit-jupiter-engine ${junit.jupiter.version} org.junit.vintage junit-vintage-engine ${junit.jupiter.version} org.apache.maven.plugins maven-compiler-plugin ${maven.compiler.version} true ${java.version} ${java.version} ${maven.compiler.encoding}
    <plugin>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-maven</artifactId>
        <version>${allure.maven.version}</version>
        <configuration>
            <reportVersion>${allure.version}</reportVersion>
            <allureDownloadUrl>${allure.cmd.download.url}/${allure.version}/allure-commandline-${allure.version}.zip</allureDownloadUrl>
        </configuration>
    </plugin>
</plugins>
```