使用 Fastjson 的?JSONPath.eval
?可以通過?JSONPath 表達式直接定位多層級 JSON 中的目標字段,避免逐層調用?getJSONObject()
?的繁瑣操作。以下是具體實現方法和示例:
核心思路
通過?JSONPath.eval
?方法,傳入 JSON 對象(或 JSON 字符串)和?JSONPath 表達式,直接提取目標字段的值。JSONPath 表達式類似 XPath,用簡潔的路徑語法描述嵌套結構(例如?$.user.info.contact.email
?表示根節點下?user
?對象的?info
?對象的?contact
?對象的?email
?字段)。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;public class JsonPathEvalDemo {public static void main(String[] args) {// 示例多層級 JSON 數據(與之前保持一致)String jsonStr = "{\n" +" \"user\": {\n" +" \"info\": {\n" +" \"name\": \"張三\",\n" +" \"age\": 25,\n" +" \"contact\": {\n" +" \"email\": \"zhangsan@example.com\",\n" +" \"phone\": \"138-1234-5678\"\n" +" }\n" +" },\n" +" \"login\": {\n" +" \"last_login_time\": \"2025-05-05 20:30:00\",\n" +" \"is_valid\": true\n" +" }\n" +" }\n" +"}";try {// 1. 解析 JSON 字符串為 JSONObjectJSONObject root = JSON.parseObject(jsonStr);// 2. 逐層獲取嵌套對象JSONObject user = root.getJSONObject("user"); // 獲取 "user" 對象JSONObject info = user.getJSONObject("info"); // 獲取 "info" 對象JSONObject contact = info.getJSONObject("contact"); // 獲取 "contact" 對象// 3. 獲取目標字段值(支持多種類型)String name = info.getString("name"); // 姓名(字符串)int age = info.getIntValue("age"); // 年齡(整數)String email = contact.getString("email"); // 郵箱(字符串)boolean isValid = user.getJSONObject("login").getBooleanValue("is_valid"); // 登錄有效性(布爾值)// 輸出結果System.out.println("姓名: " + name);System.out.println("年齡: " + age);System.out.println("郵箱: " + email);System.out.println("登錄有效性: " + isValid);} catch (Exception e) {e.printStackTrace();System.out.println("解析 JSON 失敗: " + e.getMessage());}// 解析 JSON 為 JSONObject(或直接對 JSON 字符串使用 JSONPath)JSONObject root = JSON.parseObject(jsonStr);try {// 1. 用 JSONPath 表達式直接獲取目標字段String name = (String) JSONPath.eval(root, "$.user.info.name"); // 姓名Integer age = (Integer) JSONPath.eval(root, "$.user.info.age"); // 年齡String email = (String) JSONPath.eval(root, "$.user.info.contact.email");// 郵箱Boolean isValid = (Boolean) JSONPath.eval(root, "$.user.login.is_valid");// 登錄有效性// 2. 輸出結果System.out.println("姓名: " + name);System.out.println("年齡: " + age);System.out.println("郵箱: " + email);System.out.println("登錄有效性: " + isValid);// 3. 擴展:直接對 JSON 字符串使用(無需先解析為 JSONObject)String lastLoginTime = (String) JSONPath.eval(jsonStr, "$.user.login.last_login_time");System.out.println("最后登錄時間: " + lastLoginTime);} catch (Exception e) {e.printStackTrace();System.out.println("JSONPath 解析失敗: " + e.getMessage());}}
}
1. JSONPath 表達式語法
$
:表示根節點(類似 XPath 的?/
)。.
?或?[]
:訪問子節點(例如?$.user
?或?$['user']
?效果相同)。- 嵌套層級:用連續的?
.
?拼接路徑(例如?$.user.info.contact.email
)。 - 數組支持:若字段是數組,可用?
[index]
?定位元素(例如?$.users[0].name
?表示第一個用戶的姓名)。
2.字段不存在處理
若路徑不存在,JSONPath.eval
?會返回?null
(不會拋異常),需注意判空:
String email = (String) JSONPath.eval(root, "$.user.info.contact.email");
if (email == null) {System.out.println("郵箱字段不存在");
}
高級用法(可選)
- 通配符?
*
:匹配所有子節點(例如?$.user.info.*
?獲取?info
?下所有字段)。 - 過濾表達式:用?
?()
?篩選符合條件的元素(例如?$.users[?(@.age > 20)]
?篩選年齡大于 20 的用戶)。 - 遞歸匹配?
..
:遞歸查找所有層級的目標字段(例如?$..email
?匹配所有層級的?email
?字段)。
通過?JSONPath.eval
,可以更簡潔、靈活地處理多層級 JSON 數據,尤其適合嵌套深、結構復雜的場景。