Java JSON提取工具JsonExtractor的使用

 更新时间:2023年05月19日 16:34:49   作者:乐征skyline  
本文主要介绍了Java JSON提取工具JsonExtractor的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 问题场景

Java处理JSON数据通常的做法就是通过第三方库将其转换为一个Java类的对象,但是这样会导致产生很多跟产品业务无关的临时类。在JavaScript中,则可以直接提取,例如obj.user.name,非常方便。但是在Java中,如果不转换为类的对象,就得小心翼翼地编写像下面这样的代码:

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();
}

这样的方式非常繁琐,而且里面充满防御性的代码,显得罗嗦,关键信息其实只有jsonStr.user.name这样。而本文要介绍的就是不将JSON数据转换为某个 Java Bean 对象来提取JSON数据内容的一个工具类--JsonExtractor。

2. 功能介绍

这个类比较简单,但是方法不少,因此我将这个类里的方法分为两类来讲

2.1 构建方法

如名,用于构建JsonExtractor的方法,这里不推荐直接调用构造方法,而是以下几个方法来构建

  • 静态方法Builder from(String json):这个方法是整个过程的开始,传入参数为需要解析的JSON字符串,返回的对象是用于构建JsonExtractor的建造者。
  • 建造者方法JsonExtractor<Integer, JsonArray> forJsonArray():这个方法指定要处理的JSON数组是数组类型,返回对应的处理JSON数组的提取器。
  • 建造者方法JsonExtractor<Void, JsonNull> forNull():这个方法指定要处理的JSON数据是null,基本不用。
  • 建造者方法JsonExtractor<Void, JsonPrimitive> forPrimitive():这个方法指定要处理的JSON数据是原始类型(例如,int、String等等),返回处理原始类型的提取器。
  • 建造者方法JsonExtractor<String, JsonObject> forJsonObject():这个方法指定要处理的JSON数据是JSON对象,返回处理JSON对象的提取器,比较常用。

2.2 提取方法

这些方法的参数根据JsonExtractor的泛型K决定,如果当前对象为数组,则K为Integer,表示数组的索引;如果是对象,则K为String,表示属性对应的键值;如果是原始类型或null,由于没有下一级属性或内容,因此为Void。

  • JsonArray getArray(K key):提取对应键值的属性为数组。
  • Optional<JsonArray> optArray(K key):getArray的Optional版本。
  • int getInt(K key):提取对应键值的属性为int,没有则返回0。
  • Optional<Integer> optInt(K key):getInt的Optional版本。
  • boolean getBool(K key):提取对应键值的属性为boolean,没有则返回false。
  • Optional<Boolean> optBool(K key):getBool的Optional版本。
  • long getLong(K key):提取对应键值的属性为long,没有则返回0。
  • Optional<Long> optLong(K key):getLong的Optional版本。
  • String getString(K key):提取对应键值的属性为字符串,没有则返回空字符串。
  • 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):对指定键值的属性进行下一步提取,用于像data.user.name这样的多级提取。
  • void forEach(BiConsumer<K, JsonElement> entryConsumer):对JSON数据的内容进行遍历。

3. 使用示例

例如,我们要提取的json如下:

{
  "id": 1,
  "name": "Li Lei",
  "pet": {
    "name": "huahua",
    "type": "dog",
    "id": 11
  },
  "live": true,
  "age": 20,
  "friends": [
    "James",
    "Andy",
    "Tom"
  ]
}

对应的 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风格获取基本类型的属性
extractor.optString("name").ifPresent((String name) -> {
    System.out.println("name:" + name);
});
extractor.optString("name").ifPresent(System.out::println);
//按Optional风格获取属性并手动转换为指定类
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风格获取属性自动转换为指定类
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 这样的风格
extractor.into("pet").forJsonObject()
        .optString("name").ifPresent((String name) -> {
            System.out.println("pet.name:" + name);
        });
//提取并遍历数组
extractor.into("friends").forJsonArray()
        .forEach((Integer index, JsonElement element) -> {
            System.out.println(index + ":" + element.getAsString());
        });

4. 完整实现

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);
        }
    }
}

到此这篇关于Java JSON提取工具JsonExtractor的使用的文章就介绍到这了,更多相关Java JSON提取工具JsonExtractor内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JWT原理与java操作jwt验证详解

    JWT原理与java操作jwt验证详解

    这篇文章主要介绍了JWT原理与java操作jwt验证,详细分析了JWT的基本概念、原理与java基于JWT进行token验证的相关操作技巧,需要的朋友可以参考下
    2023-06-06
  • JAVA 中实现整句汉字拆分、转换为ASCII实例详解

    JAVA 中实现整句汉字拆分、转换为ASCII实例详解

    这篇文章主要介绍了JAVA 中实现整句汉字拆分、转换为ASCII实例详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • 如何使用新方式编写Spring MVC接口

    如何使用新方式编写Spring MVC接口

    这篇文章主要介绍了如何使用新方式编写Spring MVC接口,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • 源码分析Java中ThreadPoolExecutor的底层原理

    源码分析Java中ThreadPoolExecutor的底层原理

    这篇文章主要带大家从源码分析一下Java中ThreadPoolExecutor的底层原理,文中的示例代码讲解详细,具有一定的学习价值,需要的可以参考一下
    2023-05-05
  • SpringBoot中AOP的动态匹配和静态匹配详解

    SpringBoot中AOP的动态匹配和静态匹配详解

    这篇文章主要介绍了SpringBoot中AOP的动态匹配和静态匹配详解,在创建代理的时候对目标类的每个连接点使用静态切点检查,如果仅通过静态切点检查就可以知道连接点是不匹配的,则在运行时就不再进行动态检查了,需要的朋友可以参考下
    2023-09-09
  • EasyExcel工具读取Excel空数据行问题的解决办法

    EasyExcel工具读取Excel空数据行问题的解决办法

    EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单,节省内存著称,下面这篇文章主要给大家介绍了关于EasyExcel工具读取Excel空数据行问题的解决办法,需要的朋友可以参考下
    2022-08-08
  • 解决springcloud-gateway限流遇到的问题

    解决springcloud-gateway限流遇到的问题

    这篇文章主要介绍了解决springcloud-gateway限流遇到的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 使用Java快速将Web中表格转换成Excel的方法

    使用Java快速将Web中表格转换成Excel的方法

    在平时做系统项目时,经常会需要做导出功能,下面这篇文章主要给大家介绍了关于使用Java快速将Web中表格转换成Excel的相关资料,需要的朋友可以参考下
    2023-06-06
  • SpringBoot用实体接收Get请求传递过来的多个参数的两种方式

    SpringBoot用实体接收Get请求传递过来的多个参数的两种方式

    本文主要介绍SpringBoot用实体接收Get请求传递过来的多个参数,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 详解idea+maven打jar包的两种方式

    详解idea+maven打jar包的两种方式

    这篇文章主要介绍了idea+maven打jar包的两种方式,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07

最新评论