最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于json解析神器 jsonpath的使用說明

 更新時間:2021年02月20日 10:37:33   作者:lijie_cq  
這篇文章主要介紹了基于json解析神器 jsonpath的使用說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

如果項目需求是從某些復雜的json里面取值進行計算,用jsonpath+IK(ik-expression)來處理十分方便,jsonpath用來取json里面的值然后用IK自帶的函數(shù)進行計算,如果是特殊的計算那就自定義IK方法搞定,配置化很方便.

下面簡單介紹下jsonpath的使用方法,主要測試都在JsonPathDemo類里面:

下面是一個簡單的java項目demo:

注意: 其中他的max,min,avg,stddev函數(shù)只能類似于如下處理:

//正確寫法 但是感覺很雞肋
context.read("$.avg($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");

不能傳入list 感覺比較雞肋,如果傳入list 他會報錯(如下錯誤寫法):

//這樣會報錯
Object maxV = context.read("$.max($.result.records[*].loan_type)");
//這樣也會報錯
Object maxV = context.read("$.result.records[*].loan_type.max()");
//如果json文件中是這樣:"loan_type":"2",也會報錯,"loan_type":2 這樣才被認為是數(shù)字

報錯信息都一樣, 如下:

Exception in thread "main" com.jayway.jsonpath.JsonPathException: Aggregation function attempted to calculate value using empty array

JsonPathDemo是一個測試demo:

public class JsonPathDemo {
 public static void main(String[] args) {
 String json = FileUtils.readFileByLines("demo.json");
 ReadContext context = JsonPath.parse(json);
 //1 返回所有name
 List<String> names = context.read("$.result.records[*].name");
 //["張三","李四","王五"]
 System.out.println(names);
 //2 返回所有數(shù)組的值
 List<Map<String, String>> objs = context.read("$.result.records[*]");
 //[{"name":"張三","pid":"500234199212121212","mobile":"18623456789","applied_at":"3","confirmed_at":"5","confirm_type":"overdue","loan_type":"1","test":"mytest","all":"2"},{"name":"李四","pid":"500234199299999999","mobile":"13098765432","applied_at":"1","confirmed_at":"","confirm_type":"overdue","loan_type":"3","all":"3"},{"name":"王五","pid":"50023415464654659","mobile":"1706454894","applied_at":"-1","confirmed_at":"","confirm_type":"overdue","loan_type":"3"}]
 System.out.println(objs);
 //3 返回第一個的name
 String name0 = context.read("$.result.records[0].name");
 //張三
 System.out.println(name0);
 //4 返回下標為0 和 2 的數(shù)組值
 List<String> name0and2 = context.read("$.result.records[0,2].name");
 //["張三","王五"]
 System.out.println(name0and2);
 //5 返回下標為0 到 下標為1的 的數(shù)組值 這里[0:2] 表示包含0 但是 不包含2
 List<String> name0to2 = context.read("$.result.records[0:2].name");
 //["張三","李四"]
 System.out.println(name0to2);
 //6 返回數(shù)組的最后兩個值
 List<String> lastTwoName = context.read("$.result.records[-2:].name");
 //["李四","王五"]
 System.out.println(lastTwoName);
 //7 返回下標為1之后的所有數(shù)組值 包含下標為1的
 List<String> nameFromOne = context.read("$.result.records[1:].name");
 //["李四","王五"]
 System.out.println(nameFromOne);
 //8 返回下標為3之前的所有數(shù)組值 不包含下標為3的
 List<String> nameEndTwo = context.read("$.result.records[:3].name");
 //["張三","李四","王五"]
 System.out.println(nameEndTwo);
 //9 返回applied_at大于等于2的值
 List<Map<String, String>> records = context.read("$.result.records[?(@.applied_at >= '2')]");
 //[{"name":"張三","pid":"500234199212121212","mobile":"18623456789","applied_at":"3","confirmed_at":"5","confirm_type":"overdue","loan_type":"1","test":"mytest","all":"2"}]
 System.out.println(records);
 //10 返回name等于李四的值
 List<Map<String, String>> records0 = context.read("$.result.records[?(@.name == '李四')]");
 //[{"name":"李四","pid":"500234199299999999","mobile":"13098765432","applied_at":"1","confirmed_at":"","confirm_type":"overdue","loan_type":"3"}]
 System.out.println(records0);
 //11 返回有test屬性的數(shù)組
 List<Map<String, String>> records1 = context.read("$.result.records[?(@.test)]");
 //[{"name":"張三","pid":"500234199212121212","mobile":"18623456789","applied_at":"3","confirmed_at":"5","confirm_type":"overdue","loan_type":"1","test":"mytest","all":"2"}]
 System.out.println(records1);
 //12 返回有test屬性的數(shù)組
 List<String> list = context.read("$..all");
 //["1","4","2","3"]
 System.out.println(list);
 //12 以當前json的某個值為條件查詢 這里ok為1 取出records數(shù)組中applied_at等于1的數(shù)組
 List<String> ok = context.read("$.result.records[?(@.applied_at == $['ok'])]");
 //["1","4","2","3"]
 System.out.println(ok);
 //13 正則匹配
 List<String> regexName = context.read("$.result.records[?(@.pid =~ /.*999/i)]");
 //[{"name":"李四","pid":"500234199299999999","mobile":"13098765432","applied_at":"1","confirmed_at":"","confirm_type":"overdue","loan_type":"3","all":"3"}]
 System.out.println(regexName);
 //14 多條件
 List<String> mobile = context.read("$.result.records[?(@.all == '2' || @.name == '李四' )].mobile");
 //["18623456789","13098765432"]
 System.out.println(mobile);
 //14 查詢數(shù)組長度
 Integer length01 = context.read("$.result.records.length()");
 //3
 System.out.println(length01);
 //15 查詢list里面每個對象長度
 List<Integer> length02 = context.read("$.result.records[?(@.all == '2' || @.name == '李四' )].length()");
 //[9,8]
 System.out.println(length02);
 //16 最大值
 Object maxV = context.read("$.max($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
 //3.0
 System.out.println(maxV);
 //17 最小值
 Object minV = context.read("$.min($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
 //1.0
 System.out.println(minV);
 //18 平均值
 double avgV = context.read("$.avg($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
 //2.3333333333333335
 System.out.println(avgV);
 //19 標準差
 double stddevV = context.read("$.stddev($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
 //0.9428090415820636
 System.out.println(stddevV);
 //20 讀取一個不存在的
 String haha = context.read("$.result.haha");
 //拋出異常
 //Exception in thread "main" com.jayway.jsonpath.PathNotFoundException: No results for path: $['result']['haha']
 //at com.jayway.jsonpath.internal.path.EvaluationContextImpl.getValue(EvaluationContextImpl.java:133)
 //at com.jayway.jsonpath.JsonPath.read(JsonPath.java:187)
 //at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:102)
 //at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:89)
 //at cn.lijie.jsonpath.JsonPathDemo.main(JsonPathDemo.java:58)
 //at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 //at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 //at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 //at java.lang.reflect.Method.invoke(Method.java:498)
 //at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
 System.out.println(haha);
 }
}

pom文件引入:

 <dependency>
  <groupId>com.jayway.jsonpath</groupId>
  <artifactId>json-path</artifactId>
  <version>2.3.0</version>
 </dependency>

其中demo.json是一個測試json:

{
 "action": "/interface.service/xxx/queryBlackUserData",
 "all": "1",
 "result": {
 "count": 2,
 "tenant_count": 2,
 "records": [
 {
 "name": "張三",
 "pid": "500234199212121212",
 "mobile": "18623456789",
 "applied_at": "3",
 "confirmed_at": "5",
 "confirm_type": "overdue",
 "loan_type": 1,
 "test": "mytest",
 "all": "2"
 },
 {
 "name": "李四",
 "pid": "500234199299999999",
 "mobile": "13098765432",
 "applied_at": "1",
 "confirmed_at": "",
 "confirm_type": "overdue",
 "loan_type": 3,
 "all": "3"
 },
 {
 "name": "王五",
 "pid": "50023415464654659",
 "mobile": "1706454894",
 "applied_at": "-1",
 "confirmed_at": "",
 "confirm_type": "overdue",
 "loan_type": 3
 }
 ],
 "all": "4"
 },
 "code": 200,
 "subtime": "1480495123550",
 "status": "success",
 "ok": 3
}

FileUtils類是用于讀取xx.json文件為字符串的json:

public class FileUtils {
 /**
 * 以行為單位讀取文件,常用于讀面向行的格式化文件
 */
 public static String readFileByLines(String fileName) {
 File file = new File(fileName);
 BufferedReader reader = null;
 String str = "";
 try {
  InputStream is = FileUtils.class.getClassLoader().getResourceAsStream(fileName);
  reader = new BufferedReader(new InputStreamReader(is));
  String tempString = null;
  int line = 1;
  // 一次讀入一行,直到讀入null為文件結(jié)束
  while ((tempString = reader.readLine()) != null) {
  // 顯示行號
  str += tempString;
  }
  reader.close();
 } catch (IOException e) {
  e.printStackTrace();
 } finally {
  if (reader != null) {
  try {
   reader.close();
  } catch (IOException e1) {
  }
  }
 }
 return str;
 }
}

補充:json接口測試的利器jsonpath

在測試REST接口的時候,經(jīng)常要解析JSON,那么可以使用開源jsonpath進行,其中看網(wǎng)上看到相關(guān)的說法不錯的使用場景為:

1、接口關(guān)聯(lián)

也稱為關(guān)聯(lián)參數(shù)。在應用業(yè)務接口中,完成一個業(yè)務功能時,有時候一個接口可能不滿足業(yè)務的整個流程邏輯,需要多個接口配合使用,簡單的案例如:B接口的成功調(diào)用依賴于A接口,需要在A接口的響應數(shù)據(jù)(response)中拿到需要的字段,在調(diào)用B接口的時候,傳遞給B接口作為B接口請求參數(shù),拿到后續(xù)響應的響應數(shù)據(jù)。

接口關(guān)聯(lián)通??梢允褂谜齽t表達式去提取需要的數(shù)據(jù),但對于json這種簡潔、清晰層次結(jié)構(gòu)、輕量級的數(shù)據(jù)交互格式,使用正則未免有點殺雞用牛刀的感覺(是的,因為我不擅長寫正則表達式),我們需要更加簡單、直接的提取json數(shù)據(jù)的方式。

2、數(shù)據(jù)驗證

這里的數(shù)據(jù)驗證指的是對響應結(jié)果進行數(shù)據(jù)的校驗

接口自動化測試中,對于簡單的響應結(jié)果(json),可以直接和期望結(jié)果進行比對,判斷是否完全相等即可。

如 json {"status":1,"msg":"登錄成功"}

3、對于格式較復雜

尤其部分數(shù)據(jù)存在不確定性、會根據(jù)實際情況變化的響應結(jié)果,簡單的判斷是否完全相等(斷言)通常會失敗。

如:

json {"status":1,"code":"10001","data":[{"id":1,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"1","unfinishedInterest":"1.0","unfinishedPrincipal":"0","repaymentDate":"2018-05-27 12:24:01","actualRepaymentDate":null,"status":"0"},{"id":2,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"2","unfinishedInterest":"1.0","unfinishedPrincipal":"0","repaymentDate":"2018-06-27 12:24:01","actualRepaymentDate":null,"status":"0"},{"id":3,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"3","unfinishedInterest":"1.0","unfinishedPrincipal":"100.00","repaymentDate":"2018-07-27 12:24:01","actualRepaymentDate":null,"status":"0"}],"msg":"獲取信息成功"}

上面的json結(jié)構(gòu)嵌套了很多信息,完整的匹配幾乎不可能成功。比如其中的createTime信息,根據(jù)執(zhí)行接口測試用例的時間每次都不一樣。同時這個時間是響應結(jié)果中較為次要的信息,在進行接口自動化測試時,是可以選擇被忽略的。

4、我們需要某種簡單的方法

能夠從json中提取出我們真正關(guān)注的信息(通常也被稱為關(guān)鍵信息)。

如提取出status的值為1,data數(shù)組中每個對象的investId都為1,data中第三個對象的unfinishedPrincipal值為100.00,只要這三個關(guān)鍵信息校驗通過,我們就認為響應結(jié)果沒有問題。

JSONPATH有點像XPATH了,語法規(guī)則小結(jié)下:

這里有個表格,說明JSONPath語法元素和對應XPath元素的對比。

XPath JSONPath Description
/ $ 表示根元素
. @ 當前元素
/ . or [] 子元素
.. n/a 父元素
// .. 遞歸下降,JSONPath是從E4X借鑒的。
* * 通配符,表示所有的元素
@ n/a 屬性訪問字符
[] []

子元素操作符

| [,]

連接操作符在XPath 結(jié)果合并其它結(jié)點集合。JSONP允許name或者數(shù)組索引。

n/a [start:end:step]

數(shù)組分割操作從ES4借鑒。

[] ?()

應用過濾表示式

n/a ()

腳本表達式,使用在腳本引擎下面。

() n/a Xpath分組

下面是一個簡單的json數(shù)據(jù)結(jié)構(gòu)代表一個書店(原始的xml文件是)

{ "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
 }
 }
}
XPath JSONPath 結(jié)果
/store/book/author $.store.book[*].author

書點所有書的作者

//author $..author

所有的作者

/store/* $.store.*

store的所有元素。所有的bookst和bicycle

/store//price $.store..price

store里面所有東西的price

//book[3] $..book[2]

第三個書

//book[last()] $..book[(@.length-1)] 最后一本書
//book[position()<3] $..book[0,1]

$..book[:2]

前面的兩本書。
//book[isbn] $..book[?(@.isbn)] 過濾出所有的包含isbn的書。
//book[price<10] $..book[?(@.price<10)] 過濾出價格低于10的書。
//* $..*

所有元素。

比如在單元測試MOCK中,就可以這樣使用:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
public class BookControllerTest { 
 @Autowired
 private MockMvc mockMvc; 
 @MockBean
 private BookRepository mockRepository; 
 /*
 {
  "timestamp":"2019-03-05T09:34:13.280+0000",
  "status":400,
  "errors":["Author is not allowed.","Please provide a price","Please provide a author"]
 }
 */
 //article : jsonpath in array
 @Test
 public void save_emptyAuthor_emptyPrice_400() throws Exception {
 
 String bookInJson = "{\"name\":\"ABC\"}"; 
 mockMvc.perform(post("/books")
  .content(bookInJson)
  .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON))
  .andDo(print())
  .andExpect(status().isBadRequest())
  .andExpect(jsonPath("$.timestamp", is(notNullValue())))
  .andExpect(jsonPath("$.status", is(400)))
  .andExpect(jsonPath("$.errors").isArray())
  .andExpect(jsonPath("$.errors", hasSize(3)))
  .andExpect(jsonPath("$.errors", hasItem("Author is not allowed.")))
  .andExpect(jsonPath("$.errors", hasItem("Please provide a author")))
  .andExpect(jsonPath("$.errors", hasItem("Please provide a price")));
 
 verify(mockRepository, times(0)).save(any(Book.class));
 
 }
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • MyBatis中map的應用與模糊查詢實現(xiàn)代碼

    MyBatis中map的應用與模糊查詢實現(xiàn)代碼

    這篇文章主要介紹了MyBatis中map的應用與模糊查詢實現(xiàn)代碼,文中通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • MyBatis和MyBatis Plus并存問題及解決

    MyBatis和MyBatis Plus并存問題及解決

    最近需要使用MyBatis和MyBatis Plus,就會導致MyBatis和MyBatis Plus并存,本文主要介紹了MyBatis和MyBatis Plus并存問題及解決,具有一定的參考價值,感興趣的可以了解一下
    2024-07-07
  • hashset去除重復值原理實例解析

    hashset去除重復值原理實例解析

    這篇文章主要介紹了hashset去除重復值原理實例解析,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • SPRINGMVC JSON數(shù)據(jù)交互如何實現(xiàn)

    SPRINGMVC JSON數(shù)據(jù)交互如何實現(xiàn)

    這篇文章主要介紹了SPRINGMVC JSON數(shù)據(jù)交互如何實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • 使用java模擬簡單的tomcat的方法詳解

    使用java模擬簡單的tomcat的方法詳解

    這篇文章主要為大家詳細介紹了java模擬簡單的tomcat的方法,使用數(shù)據(jù)庫,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Spring實現(xiàn)類私有方法的幾個問題(親測通用解決方案)

    Spring實現(xiàn)類私有方法的幾個問題(親測通用解決方案)

    現(xiàn)實的業(yè)務場景中,可能需要對Spring的實現(xiàn)類的私有方法進行測試。本文給大家分享Spring實現(xiàn)類私有方法面臨的幾個問題及解決方案,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • SpringBoot+JWT實現(xiàn)注冊、登錄、狀態(tài)續(xù)簽流程分析

    SpringBoot+JWT實現(xiàn)注冊、登錄、狀態(tài)續(xù)簽流程分析

    這篇文章主要介紹了SpringBoot+JWT實現(xiàn)注冊、登錄、狀態(tài)續(xù)簽【登錄保持】,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • Spring Boot集成Spring Cloud Security進行安全增強的方法

    Spring Boot集成Spring Cloud Security進行安全增強的方法

    Spring Cloud Security是Spring Security的擴展,它提供了對Spring Cloud體系中的服務認證和授權(quán)的支持,包括OAuth2、JWT等,這篇文章主要介紹了Spring Boot集成Spring Cloud Security進行安全增強,需要的朋友可以參考下
    2024-11-11
  • Java中HttpServletRequestWrapper的使用與原理詳解

    Java中HttpServletRequestWrapper的使用與原理詳解

    這篇文章主要介紹了Java中HttpServletRequestWrapper的使用與原理詳解,HttpServletRequestWrapper 實現(xiàn)了 HttpServletRequest 接口,可以讓開發(fā)人員很方便的改造發(fā)送給 Servlet 的請求,需要的朋友可以參考下
    2024-01-01
  • Java開發(fā)學習 Java數(shù)組操作工具

    Java開發(fā)學習 Java數(shù)組操作工具

    這篇文章主要為大家詳細介紹了自己編寫的Java數(shù)組操作工具,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04

最新評論

五家渠市| 崇文区| 宁明县| 万宁市| 宿松县| 厦门市| 婺源县| 辽阳县| 彰化市| 玛多县| 郸城县| 洪江市| 互助| 卓尼县| 衡山县| 灌南县| 乌恰县| 怀集县| 东光县| 措勤县| 涟源市| 崇文区| 敦煌市| 鄂州市| 定边县| 佳木斯市| 桂林市| 阿拉善盟| 白河县| 福建省| 上思县| 永城市| 涟源市| 呼和浩特市| 天峨县| 宝应县| 砀山县| 济阳县| 驻马店市| 阿城市| 双鸭山市|