使用 GSON 的 JsonReader 流式传输 Json 文件时,您可以将对象转储为字符串吗?

Posted

技术标签:

【中文标题】使用 GSON 的 JsonReader 流式传输 Json 文件时,您可以将对象转储为字符串吗?【英文标题】:When streaming a Json file with GSON's JsonReader, can you dump an object to string? 【发布时间】:2020-05-06 14:31:13 【问题描述】:

我正在使用 Java 使用 GSON 库来处理一个巨大的 JSON 文档。

我绝对不能将它加载到内存中,它超过 8G,如果我尝试加载它会导致 JVM 崩溃并出现 OOM。

所以我使用JsonReader来处理JSON的流。

有时我遇到BEGIN_OBJECT 只想将对象的内容转储到字符串而不是处理每个单独的元素。

例如,我正在解析这样的东西:

[  "SchemaVersion":"15.0.0.0","LibraryVersion":"16.0.7324.1200","ErrorInfo": "ErrorMessage":"Access denied. You do not have permission to perform this action or access this resource.","ErrorValue":null,"TraceCorrelationId":"03ab459e-7076-5000-c1a7-196f1fc54384","ErrorCode":-2147024891,"ErrorTypeName":"System.UnauthorizedAccessException" ,"TraceCorrelationId":"03ab459e-7076-5000-c1a7-196f1fc54384"  ]

当我到达ErrorInfo 时,我只想将其作为字符串而不是解析出来。我不想解析每一块。

代码如下:

try (InputStream is = (InputStream)response.getEntity();
           InputStreamReader inputStreamReader = new InputStreamReader(is);
           JsonReader jsonReader = new JsonReader(inputStreamReader)) 
        if (jsonReader.peek() != JsonToken.BEGIN_ARRAY) 
          return;
        
        jsonReader.beginArray();
        while (jsonReader.hasNext()) 
          jsonReader.beginObject(); // Start of the default object on every request

          jsonReader.skipValue(); // name SchemaVersion
          jsonReader.skipValue(); // value
          jsonReader.skipValue(); // name LibraryVersion
          jsonReader.skipValue(); // value
          jsonReader.skipValue(); // name ErrorInfo
          if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) 
            // I want to dump the upcoming object to string here
...

是否可以将给定开始对象的 json 阅读器的内容转储到字符串结束?

类似的问题,但不完全相同:Get a dump of a section (object) of JSON

【问题讨论】:

您是否尝试过使用 Apache Spark 读取 JSON 文件?似乎您的 JSON 格式正确。 现在就试试吧!想要将其转换为答案并获得分数? 我希望你有这个链接。我已经删除了链接和答案。我已将其发布为对您要求的答复。但我被告知删除它。祝你好运! 【参考方案1】:

特别感谢 https://***.com/users/3389828/nikhil 在 cmets 中的回答。对于这种情况,您可以使用Gson.fromJson(jsonReader, Map.class)

Gson gson = new Gson();
try (InputStream is = (InputStream)response.getEntity();
           InputStreamReader inputStreamReader = new InputStreamReader(is);
           JsonReader jsonReader = new JsonReader(inputStreamReader)) 
        if (jsonReader.peek() != JsonToken.BEGIN_ARRAY) 
          return;
        
        jsonReader.beginArray();
        while (jsonReader.hasNext()) 
          Map header = gson.fromJson(jsonReader, Map.class);
          if (header.get("ErrorInfo") != null) 
            String errorDump = ((Map)header.get("ErrorInfo")).toString();
            // Now I have the error dump I need but I also 
            // didn't load the entire thing into memory!
...

更多信息:https://javadeveloperzone.com/java-8/java-parse-large-json-file-gson-example/

【讨论】:

以上是关于使用 GSON 的 JsonReader 流式传输 Json 文件时,您可以将对象转储为字符串吗?的主要内容,如果未能解决你的问题,请参考以下文章

我如何查看从 GSON JsonReader 收到了多少字节

com.google.gson.stream.MalformedJsonException:使用 JsonReader.setLenient(true) 在将 Selenium Grid 节点注册到

Gson全解析之一:JsonReader的beginObject()

Gson全解析之二:JsonReader的其它方法

Retrofit com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept

使用 JsonReader 读取动态 json 文件