Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for reading line-wise json #1304

Closed
CodingFabian opened this issue Jul 19, 2016 · 7 comments
Closed

Support for reading line-wise json #1304

CodingFabian opened this issue Jul 19, 2016 · 7 comments

Comments

@CodingFabian
Copy link
Contributor

I am in the process of reducing garbage my application creates, and I found a place where I think I could use jackson but either this is not possible or I could not find the documentation.

I have an input stream which I read line wise. Each line contains a json object I would like to parse.
Right now I need to use a BufferedReader, call readLine and then pass the String to ObjectMapper.readTree().

Now this is bad, because it creates multiple temporary copies in memory (the buffered reader already creates garbage, the temporary string and the IOContext buffer again)
Now I could use jacksons readTree and supply an InputStream.
But This would try to read the stream fully and produce a single tree.
I would love to stop at special markers (in my case linebreaks) and resume reading.

I considered wrapping my stream and emulating line breaks with end-of-file, but I could not find the place in jackson where the end of stream is detected to fake this.

Would you think this is a viable solution (including a hint how to properly fake end of input) or could this be worth adding to jackson

or maybe this already exists?

@CodingFabian
Copy link
Contributor Author

Oh maybe worth noting: I cannot read all objects at once. I need to read them line wise, process them and then move on. otherwise memory would not suffice.
manually reading lines and using string works. So I am only asking for a performance (especially garbage avoidance) optimization.

@CodingFabian
Copy link
Contributor Author

Ok, the facility exists. Its a bit hard to find but Factory.createParser(is) and parser.readValueAsTree() will do exactly as I want. But I cannot use the ObjectMapper api, as it will close the stream. If i use the same stream and the same parser to continue reading it works.

@cowtowncoder
Copy link
Member

cowtowncoder commented Jul 19, 2016

@CodingFabian Actually there is even better method that should work: use something like:

MappingIterator<MyType> iterator = mapper.readerFor(MyType.class).readValues(source);
while (iterator.hasNextValue()) {
   MyType value = iterator.nextValue();
   // ...
}

and it should just work. You can use whatever type you want, including JsonNode and Map<String.Object>.

@CodingFabian
Copy link
Contributor Author

@cowtowncoder you are awesome! Yes this is indeed nicer. just looked at the code. For my current use case I do not need the mapping (i read json nodes) and might need to feed the input stream again in between reads. So I am pretty happy with using a stream based parser and calling readValueAsTree many times. But I imagine this API coming in handy in many more places.

@cowtowncoder
Copy link
Member

@CodingFabian Sounds good to me. In many ways what happens is identical either way, so you should be good there. One note on closing of the stream is that if you pass JsonParser to ObjectMapper or ObjectReader, parser it NOT closed, whereas if you pass InputStream, it will be closed (unless you turn of JsonParser.Feature.AUTO_CLOSE_SOURCE, in which case it won't).
But it makes sense to reuse JsonParser instance instead of opening a new one for every read.

@quaff
Copy link

quaff commented Jul 28, 2020

@CodingFabian Actually there is even better method that should work: use something like:

MappingIterator<MyType> iterator = mapper.readerFor(MyType.class).readValues(source);
while (iterator.hasMoreValues()) {
   MyType value = iterator.nextValue();
   // ...
}

and it should just work. You can use whatever type you want, including JsonNode and Map<String.Object>.

hasMoreValues should be hasNextValue

@cowtowncoder
Copy link
Member

@quaff thanks, fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants