[英]Extract Json nested objects under a specific path using inputstream in Java
Have been searching this for a while, and I've also developed something working but wondering if there is a framework that can make my life easier.已经搜索了一段时间,我也开发了一些可行的东西,但想知道是否有一个框架可以让我的生活更轻松。
The problem is simple, I have a Json InputStream representing a really large data payload.问题很简单,我有一个 Json InputStream 代表一个非常大的数据有效负载。
I know for sure that this payload contains an array of objects under a known path, and I do not want to parse the stream in memory, instead I would like to seek
on the file on the given path and extract all the objects of the nested array one at aa time as a Map<String,Object>
.我确定此有效负载包含已知路径下的对象数组,并且我不想解析 memory 中的 stream,而是想在给定路径上的文件中
seek
并提取嵌套的所有对象一次一个数组作为Map<String,Object>
。
Example:例子:
{
"store": {
"book" : [
{
"isbn": "123",
"author": "author",
"title": "title",
},
..... many more objects
]
}
}
What I need is to seek
on $.store.book
and extract individual nested objects for further processing.我需要的是在
$.store.book
上seek
并提取单个嵌套对象以进行进一步处理。
I've tried JsonPath (jayway)
but the parse method seem to load everything in memory.我已经尝试过
JsonPath (jayway)
,但解析方法似乎加载了 memory 中的所有内容。
I've then used Jackson with the stream library but the solution that I got is a bit convoluted.然后我将 Jackson 与 stream 库一起使用,但我得到的解决方案有点复杂。 Is there an easier way to achieve this?
有没有更简单的方法来实现这一点?
Thanks谢谢
One option would be to sequentially look through the data at a limited rate such as 512 or 1024 bytes at a time.一种选择是以有限的速率顺序查看数据,例如一次 512 或 1024 个字节。 You could then parse the bytes to the encoded format which is likely ISO-8859-1 or UTF-8.
然后,您可以将字节解析为可能是 ISO-8859-1 或 UTF-8 的编码格式。 You could then read all bytes until some delimiter is met, likely
]
to signify the end of the array (hopefully).然后,您可以读取所有字节,直到遇到某个分隔符,可能
]
表示数组的结尾(希望如此)。 You could then use Jackson or Gson to load just that array of objects.然后,您可以使用 Jackson 或 Gson 仅加载该对象数组。
You need ParamTOFilterBy
and FilterValue
您需要
ParamTOFilterBy
和FilterValue
If you insist on Using JSONPath the selection would look like this:如果您坚持使用JSONPath ,则选择将如下所示:
JsonPath.read(jsonAsString, "$.store.book[?(@.ParamTOFilterBy==FilterValue)]")
This question talks about filtering a JSON String.这个问题谈论过滤 JSON 字符串。 Opinion I like Jackson implementation in this answer
意见我喜欢这个答案中的 Jackson 实现
If the JSON array you're interested in can be identified by a JSON pointer, then a FilteringParserDelegate with a JsonPointerBasedFilter can do the job.如果您感兴趣的 JSON 数组可以通过 JSON 指针来识别,那么带有JsonPointerBasedFilter的FilteringParserDelegate就可以完成这项工作。 This is basically a streaming parser that skips ahead until the target is found.
这基本上是一个流式解析器,它会向前跳过直到找到目标。 Then you can continue streaming the interesting tokens, or do data binding.
然后您可以继续流式传输有趣的令牌,或进行数据绑定。
private static final ObjectMapper mapper = new ObjectMapper();
private static final JsonFactory factory = mapper.getFactory();
public static void processArrayElements(InputStream json,
JsonPointer pointerToArray,
Consumer<Map<String, Object>> consumer)
throws IOException {
JsonParser parser = new FilteringParserDelegate(
factory.createParser(json),
new JsonPointerBasedFilter(pointerToArray), false, false);
if (parser.nextToken() != JsonToken.START_ARRAY) {
throw new IOException("Expected an array but found " + parser.currentToken());
}
while (parser.nextToken() != JsonToken.END_ARRAY) {
consumer.accept(parser.readValueAs(Map.class));
}
}
To print the books:要打印书籍:
JsonPointer bookArray = JsonPointer.compile("/store/book");
processArrayElements(json, bookArray, System.out::println);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.