为了保存内存并避免OOM错误,我希望从输入流中流式传输一个大的JSON,并从中提取所需的内容。更确切地说,我希望从该JSON中提取并保存一些字符串:
1.“文件中的一些文本”
1.“文件2中的一些文本”
并将它们保存到String变量中:
String result = "some text in file \r\nsome text in file2"
我尝试使用Jackson解析JSON:
JsonFactory jsonFactory = new JsonFactory();
StringBuilder result = new StringBuilder();
try (JsonParser jsonParser = jsonFactory.createParser(jsonAsInputStream)) {
String fieldName;
while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
jsonParser.nextToken();
fieldName = jsonParser.getCurrentName();
if ("files".equals(fieldName)) {
while (true) {
jsonParser.nextToken();
fieldName = jsonParser.getCurrentName();
if ("content".equals(fieldName)) {
jsonParser.nextToken();
fieldName = jsonParser.getCurrentName();
while (true) {
if ("text".equals(fieldName)) {
result.append(jsonParser.getText());
}
}
}
}
}
}
LOGGER.info("result: {}", result);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
上面的方法根本不起作用,解决方案变得很复杂。有没有简单的方法来解析JSON输入流并从中提取一些文本?
以下是附件JSON:
{
"id": "1",
"name": "TestFile.xlsx",
"files": [
{
"id": "1",
"fileName": "TestFile.xlsx",
"types": {
"fileId": "1",
"context": [
{
"id": 1,
"contextId": "xyz",
"metadata": {
"abc": "1"
}
},
{
"id": 2,
"contextId": "abc"
}
],
"fileSettings": [
{
"id": 1,
"settingId": 1
},
{
"id": 2,
"settingId": 2
}
],
"fileAttachments": [
{
"id": 1,
"canDelete": true,
"canAttach": []
}
],
"replacements": [
{
"id": 1,
"replacementText": "xcv"
}
]
},
"content": [
{
"id": "1",
"contextList": [
1,
2,
3
],
"fileContent": {
"contentType": "text",
"subList": [
{
"id": "1",
"subList": [
{
"id": "1",
"text": "some text in file",
"type": "text"
}
]
}
]
},
"externalContent": {
"id": "1",
"children": [
{
"id": "1",
"contentType": "text corrupted",
"children": []
}
]
}
},
{
"id": "2",
"contextList": [
1,
2
],
"fileContent": {
"contentType": "text",
"subList": [
{
"id": "2",
"subList": [
{
"id": "1",
"text": "some text in file2",
"type": "text"
}
]
}
]
},
"externalContent": {
"id": "2",
"children": [
{
"id": "2",
"contentType": "text corrupted2",
"children": []
}
]
}
}
]
}
]
}
3条答案
按热度按时间mpgws1up1#
简而言之,
您有两种解决方案:
我不会记录我的代码,因为它很容易理解并适应其他库,但您可以使用Java 17(启用了预览功能)和
javax.json
(+一些Lombok for Java样板文件)开发以下代码的更高级内容:使用示例:
当然,看起来不像JsonPath那么酷,但是您可以执行以下操作:
for/if/next()
模式 Package 到通用算法中(类似于BufferedReader.readLine()
实现的或将其 Package 用于流API的算法);或者,如果可能的话,找一个好的代码生成器,它可以生成一个运行时开销尽可能小的流解析器(它的结果与你的非常相似,但是可以工作)。(如果你知道的话,请Ping我。)
0x6upsns2#
您是否选中了JsonPath?您可以使用Gson或Jackson作为提供程序,但默认情况下,它使用注重性能的Json-smart。
下面是一个基于附加JSON的示例。
JsonPath将使用大量内存。如果没有足够的内存来处理大文件,可以使用流/令牌方法。下面的代码可以处理6 GB的json文件,如果不存储文本,堆大小为900 MB或更少。
}
4bbkushb3#
对于您的问题,可能有一个非常简单的解决方案。您可以使用Jackson的“JsonParser”来流式处理您的对象,使用ObjectMapper来解析它们,而无需重新编写解析逻辑。
这看起来像这样:
如果你的每个对象都足够小(这是大多数情况下的情况),你可以很容易地处理文件与GB的数据。
唯一的问题是,如果你的一个对象是巨大的,这将不起作用。
我希望它能帮助到一些人。