Java JSON提取工具JsonExtractor的使用
1. 問題場景
Java處理JSON數(shù)據(jù)通常的做法就是通過第三方庫將其轉(zhuǎn)換為一個(gè)Java類的對象,但是這樣會(huì)導(dǎo)致產(chǎn)生很多跟產(chǎn)品業(yè)務(wù)無關(guān)的臨時(shí)類。在JavaScript中,則可以直接提取,例如obj.user.name,非常方便。但是在Java中,如果不轉(zhuǎn)換為類的對象,就得小心翼翼地編寫像下面這樣的代碼:
try {
JsonElement element = JsonParser.parseString(jsonStr);
if (element.isJsonObject()) {
JsonObject userJson = element.getAsJsonObject().getAsJsonObject("user");
if (userJson != null) {
JsonPrimitive nameJson = userJson.getAsJsonPrimitive("name");
if (nameJson != null && nameJson.isString()) {
String name = nameJson.getAsString();
}
}
}
} catch (JsonParseException e) {
e.printStackTrace();
}這樣的方式非常繁瑣,而且里面充滿防御性的代碼,顯得羅嗦,關(guān)鍵信息其實(shí)只有jsonStr.user.name這樣。而本文要介紹的就是不將JSON數(shù)據(jù)轉(zhuǎn)換為某個(gè) Java Bean 對象來提取JSON數(shù)據(jù)內(nèi)容的一個(gè)工具類--JsonExtractor。
2. 功能介紹
這個(gè)類比較簡單,但是方法不少,因此我將這個(gè)類里的方法分為兩類來講
2.1 構(gòu)建方法
如名,用于構(gòu)建JsonExtractor的方法,這里不推薦直接調(diào)用構(gòu)造方法,而是以下幾個(gè)方法來構(gòu)建
- 靜態(tài)方法Builder from(String json):這個(gè)方法是整個(gè)過程的開始,傳入?yún)?shù)為需要解析的JSON字符串,返回的對象是用于構(gòu)建JsonExtractor的建造者。
- 建造者方法JsonExtractor<Integer, JsonArray> forJsonArray():這個(gè)方法指定要處理的JSON數(shù)組是數(shù)組類型,返回對應(yīng)的處理JSON數(shù)組的提取器。
- 建造者方法JsonExtractor<Void, JsonNull> forNull():這個(gè)方法指定要處理的JSON數(shù)據(jù)是null,基本不用。
- 建造者方法JsonExtractor<Void, JsonPrimitive> forPrimitive():這個(gè)方法指定要處理的JSON數(shù)據(jù)是原始類型(例如,int、String等等),返回處理原始類型的提取器。
- 建造者方法JsonExtractor<String, JsonObject> forJsonObject():這個(gè)方法指定要處理的JSON數(shù)據(jù)是JSON對象,返回處理JSON對象的提取器,比較常用。
2.2 提取方法
這些方法的參數(shù)根據(jù)JsonExtractor的泛型K決定,如果當(dāng)前對象為數(shù)組,則K為Integer,表示數(shù)組的索引;如果是對象,則K為String,表示屬性對應(yīng)的鍵值;如果是原始類型或null,由于沒有下一級屬性或內(nèi)容,因此為Void。
- JsonArray getArray(K key):提取對應(yīng)鍵值的屬性為數(shù)組。
- Optional<JsonArray> optArray(K key):getArray的Optional版本。
- int getInt(K key):提取對應(yīng)鍵值的屬性為int,沒有則返回0。
- Optional<Integer> optInt(K key):getInt的Optional版本。
- boolean getBool(K key):提取對應(yīng)鍵值的屬性為boolean,沒有則返回false。
- Optional<Boolean> optBool(K key):getBool的Optional版本。
- long getLong(K key):提取對應(yīng)鍵值的屬性為long,沒有則返回0。
- Optional<Long> optLong(K key):getLong的Optional版本。
- String getString(K key):提取對應(yīng)鍵值的屬性為字符串,沒有則返回空字符串。
- Optional<String> optString(K key):getString的Optional版本。
- JsonElement get(K key)和<T> T get(K key, Class<T> typeClass):提取指定鍵值的屬性為JsonElement或指定Java類型。
- Optional<JsonElement> opt(K key)和<T> Optional<T> opt(K key, Class<T> typeClass):get的Optional版本。
- Builder into(K key):對指定鍵值的屬性進(jìn)行下一步提取,用于像data.user.name這樣的多級提取。
- void forEach(BiConsumer<K, JsonElement> entryConsumer):對JSON數(shù)據(jù)的內(nèi)容進(jìn)行遍歷。
3. 使用示例
例如,我們要提取的json如下:
{
"id": 1,
"name": "Li Lei",
"pet": {
"name": "huahua",
"type": "dog",
"id": 11
},
"live": true,
"age": 20,
"friends": [
"James",
"Andy",
"Tom"
]
}對應(yīng)的 Java Bean 如下:
class Pet {
? ? private String name;
? ? private String type;
? ? private long id;
? ? public String getName() {
? ? ? ? return name;
? ? }
? ? public void setName(String name) {
? ? ? ? this.name = name;
? ? }
? ? public String getType() {
? ? ? ? return type;
? ? }
? ? public void setType(String type) {
? ? ? ? this.type = type;
? ? }
? ? public long getId() {
? ? ? ? return id;
? ? }
? ? public void setId(long id) {
? ? ? ? this.id = id;
? ? }
}
class User {
? ? private long id;
? ? private String name;
? ? private Pet pet;
? ? private boolean live;
? ? private int age;
? ? private String[] friends;
? ? public String[] getFriends() {
? ? ? ? return friends;
? ? }
? ? public void setFriends(String[] friends) {
? ? ? ? this.friends = friends;
? ? }
? ? public boolean isLive() {
? ? ? ? return live;
? ? }
? ? public void setLive(boolean live) {
? ? ? ? this.live = live;
? ? }
? ? public int getAge() {
? ? ? ? return age;
? ? }
? ? public void setAge(int age) {
? ? ? ? this.age = age;
? ? }
? ? public Pet getPet() {
? ? ? ? return pet;
? ? }
? ? public void setPet(Pet pet) {
? ? ? ? this.pet = pet;
? ? }
? ? public long getId() {
? ? ? ? return id;
? ? }
? ? public void setId(long id) {
? ? ? ? this.id = id;
? ? }
? ? public String getName() {
? ? ? ? return name;
? ? }
? ? public void setName(String name) {
? ? ? ? this.name = name;
? ? }
}那么提取代碼就是:
String json = "{\"id\":1,\"name\":\"Li Lei\",\"pet\":{\"name\":\"huahua\",\"type\":\"dog\",\"id\":11},\"live\":true,\"age\":20,\"friends\":[\"James\",\"Andy\",\"Tom\"]}";
JsonExtractor<String, JsonObject> extractor = JsonExtractor.from(json).forJsonObject();
//直接獲取屬性
long id = extractor.getLong("id");
//按Optional風(fēng)格獲取基本類型的屬性
extractor.optString("name").ifPresent((String name) -> {
? ? System.out.println("name:" + name);
});
extractor.optString("name").ifPresent(System.out::println);
//按Optional風(fēng)格獲取屬性并手動(dòng)轉(zhuǎn)換為指定類
extractor.opt("pet").ifPresent((JsonElement element) -> {
? ? System.out.println("pet json:" + element);
? ? Pet pet = new Gson().fromJson(element, Pet.class);
? ? System.out.println("pet bean 1:" + pet.getName());
});
//按Optional風(fēng)格獲取屬性自動(dòng)轉(zhuǎn)換為指定類
extractor.opt("pet", Pet.class).ifPresent((Pet pet) -> {
? ? System.out.println("pet bean 2:" + pet.getName());
});
//直接將屬性提取為指定類型
Pet pet = extractor.get("pet", Pet.class);
//提取多級字段,類似js的 user.pet.name 這樣的風(fēng)格
extractor.into("pet").forJsonObject()
? ? ? ? .optString("name").ifPresent((String name) -> {
? ? ? ? ? ? System.out.println("pet.name:" + name);
? ? ? ? });
//提取并遍歷數(shù)組
extractor.into("friends").forJsonArray()
? ? ? ? .forEach((Integer index, JsonElement element) -> {
? ? ? ? ? ? System.out.println(index + ":" + element.getAsString());
? ? ? ? });4. 完整實(shí)現(xiàn)
import com.google.gson.*;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
public abstract class JsonExtractor<K, V> {
? ? private static final Gson gson = new Gson();
? ? protected V jsonElement;
? ? JsonExtractor(V jsonElement) {
? ? ? ? this.jsonElement = jsonElement;
? ? }
? ? public V getJsonElement() {
? ? ? ? return jsonElement;
? ? }
? ? public static class Builder {
? ? ? ? private JsonElement element;
? ? ? ? protected Builder() {
? ? ? ? }
? ? ? ? public Builder(JsonElement element) {
? ? ? ? ? ? this.element = element;
? ? ? ? }
? ? ? ? public JsonExtractor<Void, JsonNull> forNull() {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return new NullExtractor(element.getAsJsonNull());
? ? ? ? ? ? } catch (RuntimeException e) {
? ? ? ? ? ? ? ? return new ErrorExtractor<>(e);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? public JsonExtractor<Void, JsonPrimitive> forPrimitive() {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return new PrimitiveExtractor(element.getAsJsonPrimitive());
? ? ? ? ? ? } catch (RuntimeException e) {
? ? ? ? ? ? ? ? return new ErrorExtractor<>(e);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? public JsonExtractor<String, JsonObject> forJsonObject() {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return new ObjectExtractor(element.getAsJsonObject());
? ? ? ? ? ? } catch (RuntimeException e) {
? ? ? ? ? ? ? ? return new ErrorExtractor<>(e);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? public JsonExtractor<Integer, JsonArray> forJsonArray() {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return new ArrayExtractor(element.getAsJsonArray());
? ? ? ? ? ? } catch (RuntimeException e) {
? ? ? ? ? ? ? ? return new ErrorExtractor<>(e);
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? private static class ErrorBuilder extends Builder {
? ? ? ? private final Exception exception;
? ? ? ? public ErrorBuilder(Exception exception) {
? ? ? ? ? ? this.exception = exception;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public JsonExtractor<Integer, JsonArray> forJsonArray() {
? ? ? ? ? ? return new ErrorExtractor<>(exception);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public JsonExtractor<Void, JsonNull> forNull() {
? ? ? ? ? ? return new ErrorExtractor<>(exception);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public JsonExtractor<Void, JsonPrimitive> forPrimitive() {
? ? ? ? ? ? return new ErrorExtractor<>(exception);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public JsonExtractor<String, JsonObject> forJsonObject() {
? ? ? ? ? ? return new ErrorExtractor<>(exception);
? ? ? ? }
? ? }
? ? public static Builder from(String json) {
? ? ? ? try {
? ? ? ? ? ? return new Builder(JsonParser.parseString(json));
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? return new ErrorBuilder(e);
? ? ? ? }
? ? }
? ? public Builder into(K key) {
? ? ? ? return new ErrorBuilder(new RuntimeException("not implements!"));
? ? }
? ? public Optional<JsonElement> opt(K key) {
? ? ? ? return Optional.ofNullable(get(key));
? ? }
? ? public <T> Optional<T> opt(K key, Class<T> typeClass) {
? ? ? ? return Optional.empty();
? ? }
? ? public JsonElement get(K key) {
? ? ? ? return null;
? ? }
? ? public <T> T get(K key, Class<T> typeClass) {
? ? ? ? return opt(key, typeClass).orElse(null);
? ? }
? ? public JsonArray getArray(K key) {
? ? ? ? return null;
? ? }
? ? public Optional<JsonArray> optArray(K key) {
? ? ? ? return Optional.ofNullable(getArray(key));
? ? }
? ? public int getInt(K key) {
? ? ? ? return optInt(key).orElse(0);
? ? }
? ? public Optional<Integer> optInt(K key) {
? ? ? ? return Optional.empty();
? ? }
? ? public double getDouble(K key) {
? ? ? ? return optDouble(key).orElse(0d);
? ? }
? ? public Optional<Double> optDouble(K key) {
? ? ? ? return Optional.empty();
? ? }
? ? public boolean getBool(K key) {
? ? ? ? return optBool(key).orElse(false);
? ? }
? ? public Optional<Boolean> optBool(K key) {
? ? ? ? return Optional.empty();
? ? }
? ? public long getLong(K key) {
? ? ? ? return optLong(key).orElse(0L);
? ? }
? ? public Optional<Long> optLong(K key) {
? ? ? ? return Optional.empty();
? ? }
? ? public String getString(K key) {
? ? ? ? return optString(key).orElse("");
? ? }
? ? public Optional<String> optString(K key) {
? ? ? ? return Optional.empty();
? ? }
? ? public void forEach(BiConsumer<K, JsonElement> entryConsumer) {
? ? }
? ? private static class ObjectExtractor extends JsonExtractor<String, JsonObject> {
? ? ? ? private ObjectExtractor(JsonObject jsonObject) {
? ? ? ? ? ? super(jsonObject);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Builder into(String key) {
? ? ? ? ? ? JsonElement element = this.jsonElement.get(key);
? ? ? ? ? ? return element == null ? new Builder(JsonNull.INSTANCE) : new Builder(element);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public JsonElement get(String key) {
? ? ? ? ? ? return this.jsonElement.getAsJsonObject(key);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<JsonArray> optArray(String key) {
? ? ? ? ? ? return Optional.ofNullable(this.jsonElement.getAsJsonArray(key));
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<Integer> optInt(String key) {
? ? ? ? ? ? return Optional.ofNullable(this.jsonElement.getAsJsonPrimitive(key)).map(JsonPrimitive::getAsInt);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<Double> optDouble(String key) {
? ? ? ? ? ? return Optional.ofNullable(jsonElement.getAsJsonPrimitive(key)).map(JsonPrimitive::getAsDouble);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<Boolean> optBool(String key) {
? ? ? ? ? ? return Optional.ofNullable(jsonElement.getAsJsonPrimitive(key)).map(JsonPrimitive::getAsBoolean);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<Long> optLong(String key) {
? ? ? ? ? ? return Optional.ofNullable(jsonElement.getAsJsonPrimitive(key)).map(JsonPrimitive::getAsLong);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<String> optString(String key) {
? ? ? ? ? ? return Optional.ofNullable(jsonElement.getAsJsonPrimitive(key)).map(JsonPrimitive::getAsString);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public <T> Optional<T> opt(String key, Class<T> typeClass) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return Optional.ofNullable(jsonElement.get(key)).map(e -> gson.fromJson(e, typeClass));
? ? ? ? ? ? } catch (JsonSyntaxException e) {
? ? ? ? ? ? ? ? return Optional.empty();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void forEach(BiConsumer<String, JsonElement> entryConsumer) {
? ? ? ? ? ? Set<Map.Entry<String, JsonElement>> entrySet = jsonElement.entrySet();
? ? ? ? ? ? for (Map.Entry<String, JsonElement> entry : entrySet) {
? ? ? ? ? ? ? ? entryConsumer.accept(entry.getKey(), entry.getValue());
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? private static class ArrayExtractor extends JsonExtractor<Integer, JsonArray> {
? ? ? ? private ArrayExtractor(JsonArray array) {
? ? ? ? ? ? super(array);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Builder into(Integer index) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return new Builder(getJsonElement().get(index));
? ? ? ? ? ? } catch (IndexOutOfBoundsException e) {
? ? ? ? ? ? ? ? return new ErrorBuilder(e);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public JsonElement get(Integer index) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return getJsonElement().get(index);
? ? ? ? ? ? } catch (IndexOutOfBoundsException e) {
? ? ? ? ? ? ? ? return null;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<JsonArray> optArray(Integer index) {
? ? ? ? ? ? return Optional.ofNullable(getJsonElement().get(index)).map(JsonElement::getAsJsonArray);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<Integer> optInt(Integer index) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return Optional.ofNullable(getJsonElement().get(index)).map(JsonElement::getAsInt);
? ? ? ? ? ? } catch (IndexOutOfBoundsException e) {
? ? ? ? ? ? ? ? return Optional.empty();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<Double> optDouble(Integer index) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return Optional.ofNullable(getJsonElement().get(index)).map(JsonElement::getAsDouble);
? ? ? ? ? ? } catch (IndexOutOfBoundsException e) {
? ? ? ? ? ? ? ? return Optional.empty();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<Boolean> optBool(Integer index) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return Optional.ofNullable(getJsonElement().get(index)).map(JsonElement::getAsBoolean);
? ? ? ? ? ? } catch (IndexOutOfBoundsException e) {
? ? ? ? ? ? ? ? return Optional.empty();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<Long> optLong(Integer index) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return Optional.ofNullable(getJsonElement().get(index)).map(JsonElement::getAsLong);
? ? ? ? ? ? } catch (IndexOutOfBoundsException e) {
? ? ? ? ? ? ? ? return Optional.empty();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Optional<String> optString(Integer index) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return Optional.ofNullable(getJsonElement().get(index)).map(JsonElement::getAsString);
? ? ? ? ? ? } catch (IndexOutOfBoundsException e) {
? ? ? ? ? ? ? ? return Optional.empty();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public <T> Optional<T> opt(Integer index, Class<T> typeClass) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return Optional.ofNullable(getJsonElement().get(index)).map(e -> gson.fromJson(e, typeClass));
? ? ? ? ? ? } catch (JsonSyntaxException e) {
? ? ? ? ? ? ? ? return Optional.empty();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void forEach(BiConsumer<Integer, JsonElement> entryConsumer) {
? ? ? ? ? ? for (int i = 0; i < getJsonElement().size(); i++) {
? ? ? ? ? ? ? ? entryConsumer.accept(i, getJsonElement().get(i));
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? private static class NullExtractor extends JsonExtractor<Void, JsonNull> {
? ? ? ? NullExtractor(JsonNull jsonElement) {
? ? ? ? ? ? super(jsonElement);
? ? ? ? }
? ? }
? ? private static class PrimitiveExtractor extends JsonExtractor<Void, JsonPrimitive> {
? ? ? ? PrimitiveExtractor(JsonPrimitive jsonElement) {
? ? ? ? ? ? super(jsonElement);
? ? ? ? }
? ? }
? ? private static class ErrorExtractor<K, V> extends JsonExtractor<K, V> {
? ? ? ? private final Exception exception;
? ? ? ? private ErrorExtractor(Exception exception) {
? ? ? ? ? ? super(null);
? ? ? ? ? ? this.exception = exception;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public Builder into(K key) {
? ? ? ? ? ? return new ErrorBuilder(exception);
? ? ? ? }
? ? }
}到此這篇關(guān)于Java JSON提取工具JsonExtractor的使用的文章就介紹到這了,更多相關(guān)Java JSON提取工具JsonExtractor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
15道非常經(jīng)典的Java面試題 附詳細(xì)答案
這篇文章主要為大家推薦了15道非常經(jīng)典的Java面試題,附詳細(xì)答案,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
java實(shí)現(xiàn)Img與PDF相互轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)Img與PDF相互轉(zhuǎn)換的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
使用Springboot實(shí)現(xiàn)word在線編輯保存
PageOffice目前支持的Web編程語言及架構(gòu)有:Java(JSP、SSH、MVC等),ASP.NET(C#、VB.NET、MVC、Razor等),PHP,ASP,本篇文章就帶你使用Springboot整合PageOffice實(shí)現(xiàn)word在線編輯保存2021-08-08
mybatis-plus多表關(guān)聯(lián)查詢功能的實(shí)現(xiàn)
本文給大家介紹mybatis-plus多表關(guān)聯(lián)查詢功能的實(shí)現(xiàn)代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-11-11
java poi導(dǎo)出excel時(shí)如何設(shè)置手動(dòng)換行
這篇文章主要介紹了java poi導(dǎo)出excel時(shí)如何設(shè)置手動(dòng)換行,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Java接口統(tǒng)一樣式返回模板的實(shí)現(xiàn)
這篇文章主要介紹了Java接口統(tǒng)一樣式返回模板的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
解決java.util.NoSuchElementException異常正確方法
java.util.NoSuchElementException是Java中的一種異常,表示在迭代器或枚舉中找不到元素,這篇文章主要給大家介紹了關(guān)于解決java.util.NoSuchElementException異常的相關(guān)資料,需要的朋友可以參考下2023-11-11

