最近要做的緩存項目中用到了jsonpath,這個工具主要是用來在多層嵌套的json中去取出對應的值。
項目介紹:
因為我們項目設計是提供一個細緻到方法參數級别的緩存,中間也用到了redis,通過将項目名,類名,方法名,參數類型,已經參數的取值規則配置到redis中去,這點是通過springaop中的環繞通知去做的,擷取某個包下的類,或者是jar包下,相對路徑下的類等,在通過反射擷取對應的方法的參數等,參數比對的話在考慮是否取值,反正邏輯有點複雜,現在還沒做完,流程不是很清楚,配置緩存規則和對應的緩存清除規則,內建到項目中去,當某個方法執行時,如果配有緩存規則,就去緩存中取出對應的資料,不然的話就繼續執行,如果某個方法配了針對于另外一個方法的緩存清除規則,那個當這個方法執行的時候會把另外一個方法中的緩存清除掉。
jsonpath使用:
github:https://github.com/json-path/JsonPath
這裡給出github的位址,功能介紹詳細,可以直接測試并使用。
下面給出自己的測試(以下代碼轉載于——>>> https://blog.csdn.net/qq_20641565/article/details/77162868)
pom檔案引入:
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.3.0</version>
</dependency>
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 傳回所有數組的值
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 的數組值
List<String> name0and2 = context.read("$.result.records[0,2].name");
//["張三","王五"]
System.out.println(name0and2);
//5 傳回下标為0 到 下标為1的 的數組值 這裡[0:2] 表示包含0 但是 不包含2
List<String> name0to2 = context.read("$.result.records[0:2].name");
//["張三","李四"]
System.out.println(name0to2);
//6 傳回數組的最後兩個值
List<String> lastTwoName = context.read("$.result.records[-2:].name");
//["李四","王五"]
System.out.println(lastTwoName);
//7 傳回下标為1之後的所有數組值 包含下标為1的
List<String> nameFromOne = context.read("$.result.records[1:].name");
//["李四","王五"]
System.out.println(nameFromOne);
//8 傳回下标為3之前的所有數組值 不包含下标為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屬性的數組
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屬性的數組
List<String> list = context.read("$..all");
//["1","4","2","3"]
System.out.println(list);
//12 以目前json的某個值為條件查詢 這裡ok為1 取出records數組中applied_at等于1的數組
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 查詢數組長度
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);
}
}
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為檔案結束
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;
}
}