gson 反序列化JSON文档中未在JSON数组中编码的多个值(连接的JSON)[已关闭]

b4lqfgs4  于 2022-11-06  发布在  其他
关注(0)|答案(3)|浏览(157)

已关闭。此问题需要更多的focused。当前不接受答案。
**想要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。

去年关闭了。
Improve this question
我有一个JSON文件,其中包含很多对象,不是列表,而是一个在另一个下面,如:

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

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

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

...

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

wfsdck30

wfsdck301#

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 JsonReader jsonReader, 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 JsonReader jsonReader, 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);
            }
        }
    };
}

作为流阅读

  • 惰性,(推/)拉语义
  • 懒惰是一种美德,流API支持,一旦流关闭,就关闭支持的资源
public static <T> Stream<T> readAsStream(final Gson gson, final JsonReader jsonReader, 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);
                }
            });
}
chy5wohz

chy5wohz2#

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

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

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

ki0zmccv

ki0zmccv3#

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

相关问题