專案特點
GitHub專案地址:https://github.com/json-path/JsonPath
主要功能:
- 將Json字串轉為Java Map物件(這個不算什麼,FastJson之類的工具都可以)
- 通過強大的規則表示式定位欄位,返回欄位值或值集合(很厲害)
支援的規則表示式以及示例(選自專案readme):
JsonPath (點選測試) | 結果 |
---|---|
$.store.book[*].author | The authors of all books |
$..author | All authors |
$.store.* | All things, both books and bicycles |
$.store..price | The price of everything |
$..book[2] | The third book |
$..book[-2] | The second to last book |
$..book[0,1] | The first two books |
$..book[:2] | All books from index 0 (inclusive) until index 2 (exclusive) |
$..book[1:2] | All books from index 1 (inclusive) until index 2 (exclusive) |
$..book[-2:] | Last two books |
$..book[2:] | Book number two from tail |
$..book[?(@.isbn)] | All books with an ISBN number |
$.store.book[?(@.price < 10)] | All books in store cheaper than 10 |
$..book[?(@.price <= $['expensive'])] | All books in store that are not "expensive" |
$..book[?(@.author =~ /.*REES/i)] | All books matching regex (ignore case) |
$..* | Give me every thing |
$..book.length() | The number of books |
實戰測試
就用專案readme文件提供的例子進行測試:
json格式字串,點選檢視
{
"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
}
POM中引入依賴:
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.7.0</version>
</dependency>
寫一個單元測試類:
@SpringBootTest
@RunWith(MockitoJUnitRunner.class)
public class JsonPathTest {
private final String jsonStr = "...";
private final Object context = Configuration.defaultConfiguration().jsonProvider().parse(jsonStr);
@Test
public void test(){}
}
其中:
- 第二個註解可以做到啟動SpringBoot測試類而無需啟動SpringApplication,並且也可以做到元件注入等功能。
- jsonStr用來指代之前所述的json字串,這裡簡略寫。
- context實際上是由json字串通過預設配置生成的一個Map<String, Object>。
先看看context的型別:
System.out.println("context的型別:" + context.getClass().getSimpleName() + "\n");
------------------------------------------------------------------
output: context的型別:LinkedHashMap
用法1:通過key定位一個value:
jsonpath = "$.store.book[1].price";
result = JsonPath.read(testMap, jsonpath);
System.out.println("contents on " + jsonpath + ": " + result + "\n");
------------------------------------------------------------------
output: contents on $.store.book[1].price: 12.99
用法2:通過key定位一組value:
jsonpath = "$.store.book[*].price";
result = JsonPath.read(context, jsonpath);
System.out.println("contents on " + jsonpath + ": " + result + "\n");
------------------------------------------------------------------
output: contents on $.store.book[*].price: [8.95,12.99,8.99,22.99]
這裡如果去檢視result的type,會發現它是JSONArray型別,是List<Object>介面的實現,當List用就可以了。
用法3:向下遞迴查詢:
jsonpath = "$..price";
result = JsonPath.read(context, jsonpath);
System.out.println("contents on " + jsonpath + ": " + result);
------------------------------------------------------------------
output: contents on $..price: [8.95,12.99,8.99,22.99,19.95]
在測試的時候想起一個問題,設想這樣的場景,如果我們已經有了這樣一個Map,只需要JsonPath提供的規則表示式解析與查詢能力,那麼想要使用JsonPath是不是需要Map->JsonString->context->規則解析->查詢結果?答案是不需要的。
我們已經知道這個context本就是一個Map型別,那麼是不是可以省去中間轉為json string的步驟呢?我們測試看看:
//1. 先將json解析為一個Map
Map<String, Object> testMap = (Map) JSONObject.parseObject(JSON_STRING);
jsonpath = "$..price";
//2. 再將Map傳入read方法,看是否能查詢到結果:
result = JsonPath.read(testMap, jsonpath);
System.out.println("contents on " + jsonpath + ": " + result);
------------------------------------------------------------------
output: contents on $..price: [8.95,12.99,8.99,22.99,19.95]
可以看出,JsonPath的搜尋規則解析能力是支援對普通Map進行查詢的。