JSON Pointer 是一個包含零個或多個引用標記的 Unicode 字符串,每個引用標記以 “/” (%x2F) 字符為前綴。如果引用標記包含 “~” (%x7E) 或 “/” (%x2F) 字符,則它們必須分別被編碼為 “~0” 和 “~1”。它的 ABNF 語法如下:
json-pointer = *( "/" reference-token )reference-token = *( unescaped / escaped )unescaped = %x00-2E / %x30-7D / %x7F-10FFFFescaped = "~" ( "0" / "1" )
如果一個 JSON 指針值不符合這個語法,則屬于錯誤的條件。
JSON Pointer 語法所有引號“"” (%x22)、反斜杠“/” (%x5C)和控制字符(%x00-1F)的實例必須被轉義。例如,給定以下JSON文檔
{ "foo": ["bar", "baz"], "": 0, "a/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i//j": 5, "k/"l": 6, " ": 7, "m~n": 8}
那么以下 JSON 字符串應用標記和對應的值:
"" // 讀取整個文檔"/foo" ["bar", "baz"]"/foo/0" "bar" // 讀取數(shù)組、集合中的第0個元素"/" 0"/a~1b" 1"/c%d" 2"/e^f" 3"/g|h" 4"/i//j" 5"/k/"l" 6"/ " 7"/m~0n" 8
示例 json 文本(節(jié)選自筆者掘金用戶信息):
{ "err_no": 0, "err_msg": "success", "data": { "user_name": "如夢技術", "description": "生活不止眼前的茍且,還有詩和遠方的田野。", "blog_address": "https://www.dreamlu", "user_growth_info": { "user_id": 1591748566975837, "jpower": 4056, "jscore": 1208.1, "jpower_level": 4, "jscore_level": 5, "jscore_title": "先鋒掘友", "author_achievement_list": [], "vip_level": 1, "vip_title": "初學乍練", "jscore_next_level_score": 2000, "jscore_this_level_mini_score": 500, "vip_score": 0 } }}
需求是只需要獲取 “jscore_title” 字段,獲取這個值按照上文的語法我們的完整引用標記為:/data/user_growth_info/jscore_title。筆者采用 mica 中的 mica-core 中的 Jsonutil作為 jackson 的輔助工具類(這應該也是市面上最好用和最全的一個 jackson json 工具類)。示例 java 代碼:
// 讀取 json 為 JsonNodeJsonNode jsonNode = JsonUtil.readTree(json);// 調用 at 方法,傳入 JSON Pointer 引用標記JsonNode titleNode = jsonNode.at("/data/user_growth_info/jscore_title");// 讀取節(jié)點文本String jsCoreTitle = titleNode.asText();System.out.println(jsCoreTitle); // 先鋒掘友
注意:使用 JSON Pointer 語法獲取不存在的節(jié)點時也不會報錯,在使用 asText、asInt 等方法獲取節(jié)點的值時會默認返回 null,當然這些方法也都有個帶默認值的方法,非常好用。另外我們也可以將某個節(jié)點轉換成 Java Bean,例如上面的 user_growth_info節(jié)點,示例代碼如下:UserGrowthInfo Bean(使用 idea GsonFormatPlus 插件生成)
@Datapublic class UserGrowthInfo { @JsonProperty("user_id") private Long userId; @JsonProperty("jpower") private Integer jpower; @JsonProperty("jscore") private Double jscore; @JsonProperty("jpower_level") private Integer jpowerLevel; @JsonProperty("jscore_level") private Integer jscoreLevel; @JsonProperty("jscore_title") private String jscoreTitle; @JsonProperty("author_achievement_list") private List<?> authorAchievementList; @JsonProperty("vip_level") private Integer vipLevel; @JsonProperty("vip_title") private String vipTitle; @JsonProperty("jscore_next_level_score") private Integer jscoreNextLevelScore; @JsonProperty("jscore_this_level_mini_score") private Integer jscoreThisLevelMiniScore; @JsonProperty("vip_score") private Integer vipScore;}
讀取 json 并轉換成 UserGrowthInfo Bean:
// 讀取 json 為 JsonNodeJsonNode jsonNode = JsonUtil.readTree(json);// 讀取 user_growth_info 節(jié)點JsonNode userGrowthInfoNode = jsonNode.at("/data/user_growth_info");// 轉換成 UserGrowthInfo beanUserGrowthInfo userGrowthInfo = JsonUtil.treeToValue(userGrowthInfoNode, UserGrowthInfo.class);System.out.println(userGrowthInfo);// 輸出結果:UserGrowthInfo(userId=1591748566975837, jpower=4056, jscore=1208.1, jpowerLevel=4, // jscoreLevel=5, jscoreTitle=先鋒掘友, authorAchievementList=[], vipLevel=1, vipTitle=初學乍練, // jscoreNextLevelScore=2000, jscoreThisLevelMiniScore=500, vipScore=0)
Jackson JSON Pointer 語法非常簡單易用,Jackson 官網文檔改版之后這個文檔很難找到了。筆者從14年開始使用,并且將她融入到很多 mica 組建中。例如使用 mica-http 來讀取我們想要的結果:
// 讀取 linkedin 郵箱private String getUserEmail(String accessToken) { return HttpRequest.get("https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))") .addHeader("Host", "api.linkedin.com") .addHeader("Connection", "Keep-Alive") .addHeader("Authorization", "Bearer " + accessToken) .execute() .asJsonNode() .at("/elements/0/handle~0/emailAddress") .asText();}
Jackson 還是非常好用的,希望此篇文章對大家有所幫助!更多精彩好文敬請關注我們!!!
本文鏈接:http://www.www897cc.com/showinfo-26-38107-0.html鮮為人知的 jackson Pointer 語法,超好用!
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com