微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

反序列化 JSON 文档中未编码在 JSON 数组中的多个值连接的 JSON 读取列表使用消费者阅读作为迭代器阅读以流形式阅读

如何解决反序列化 JSON 文档中未编码在 JSON 数组中的多个值连接的 JSON 读取列表使用消费者阅读作为迭代器阅读以流形式阅读

我有一个包含很多对象的 JSON 文件,不是一个列表,而是一个如下:

{
    "attr1": "value1","attr2": "value2","attr3": "value3",}

{
    "attr1": "value1","attr3": "value3"
}

{
    "attr1": "value1",}

...

如何获取这些对象的列表(包含 Aattr1attr2attr3 类)?

解决方法

Gson 支持所谓的“宽松”模式,该模式支持格式错误的 JSON 文档(包括奇怪的 JSON 令牌和“多合一”JSON 文档,就像您在问题中提到的那样。)这也使 Gson 能够检测 JSON用于区分多个值的文档结束标记。

一般来说,常见的算法如下:

jsonReader.setLenient(true);
final Collection<AttributeBag> actualBags = new ArrayList<>();
while ( jsonReader.peek() != JsonToken.END_DOCUMENT ) {
    actualBags.add(gson.fromJson(jsonReader,elementType));
}

这是一种临时方法,您可以使用不同的幕后机制使其更通用:

读取列表

  • 渴望,拉语义
  • 仅支持列表,可能会占用整个内存
public static <T> List<T> readList(final Gson gson,final JsonReader jsonReader,final TypeToken<? extends T> typeToken)
        throws IOException {
    final boolean isLenient = jsonReader.isLenient();
    try {
        jsonReader.setLenient(true);
        final Type type = typeToken.getType();
        final List<T> list = new ArrayList<>();
        while ( jsonReader.peek() != JsonToken.END_DOCUMENT ) {
            list.add(gson.fromJson(jsonReader,type));
        }
        return list;
    } finally {
        jsonReader.setLenient(isLenient);
    }
}

使用消费者阅读

  • 渴望,推送语义
  • 支持任何类型的消费者,不一定要添加到集合中
public static <T> void readPushing(final Gson gson,final TypeToken<? extends T> typeToken,final Consumer<? super T> consumer)
        throws IOException {
    final boolean isLenient = jsonReader.isLenient();
    try {
        jsonReader.setLenient(true);
        final Type type = typeToken.getType();
        while ( jsonReader.peek() != JsonToken.END_DOCUMENT ) {
            consumer.accept(gson.<T>fromJson(jsonReader,type));
        }
    } finally {
        jsonReader.setLenient(isLenient);
    }
}

作为迭代器阅读

  • 懒惰,拉语义
  • 迭代器因懒惰而美丽
public static <T> Iterator<T> readAsIterator(final Gson gson,final TypeToken<? extends T> typeToken) {
    final Type type = typeToken.getType();
    return new Iterator<T>() {
        @Override
        public boolean hasNext() {
            final boolean isLenient = jsonReader.isLenient();
            try {
                jsonReader.setLenient(true);
                return jsonReader.peek() != JsonToken.END_DOCUMENT;
            } catch ( final IOException ex ) {
                throw new RuntimeException(ex);
            } finally {
                jsonReader.setLenient(isLenient);
            }
        }

        @Override
        public T next() {
            final boolean isLenient = jsonReader.isLenient();
            try {
                jsonReader.setLenient(true);
                return gson.fromJson(jsonReader,type);
            } finally {
                jsonReader.setLenient(isLenient);
            }
        }
    };
}

以流形式阅读

  • 懒惰,(推/)拉语义
  • 懒惰是一种美德,Stream API 支持,一旦关闭流就关闭支持的资源
public static <T> Stream<T> readAsStream(final Gson gson,final TypeToken<? extends T> typeToken) {
    final Type type = typeToken.getType();
    final Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE,0) {
        @Override
        public boolean tryAdvance(final Consumer<? super T> action) {
            final boolean isLenient = jsonReader.isLenient();
            try {
                jsonReader.setLenient(true);
                final JsonToken token = jsonReader.peek();
                if ( token == JsonToken.END_DOCUMENT ) {
                    return false;
                }
                action.accept(gson.<T>fromJson(jsonReader,type));
                return true;
            } catch ( final IOException ex ) {
                throw new RuntimeException(ex);
            } finally {
                jsonReader.setLenient(isLenient);
            }
        }
    };
    return StreamSupport.stream(spliterator,false)
            .onClose(() -> {
                try {
                    jsonReader.close();
                } catch ( final IOException ex ) {
                    throw new RuntimeException(ex);
                }
            });
}
,

执行此操作的库是 Gson。你可以这样使用它:

    gson = Gson();
    MyObject myObject = gson.fromJson(jsonString,MyObject.class);

您可以使用 Readers 输入数据或其他类型的对象。

,

您的 JSON 文件包含数据的第一件事没有结构,因此无法直接转换为 Java 对象。您需要修改 JSON 字符串以使其成为列表。然后您可以使用以下内容来检索对象列表。

List jsonList = new ObjectMapper().readValue(new File(filepath),List.class);

之后,您可以使用 instanceOf 将 Object 转换为它们各自的类。

jsonList.foreach(jsonObject -> {
   if(jsonObject instanceOf MyClass1){
       // cast it or perform some op
   }
});

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。