问题
ObjectMapper map = new ObjectMapper(); //for later inner object data binding
JsonParser p = map.getFactory().createParser(new File("test.json"));
//start the tokenizing of object
p.nextToken();
//loop until the end object is found, simultaneously incrementing loop
while (p.nextToken() != JsonToken.END_OBJECT) {
//...
}
p.close();
(note, there is probably a better way to do what I am trying to do here and I welcome any advice on how to do this better, but please also tell me if my current technique is possible)
This is the code I currently have and have not gone any further because I realized a flaw. This code was taken from a Jackson streaming API tutorial and I am trying to adapt it to my project.
What I am trying to do is loop through the tokens of an object in a json file from the start of the object to its end. However, this json file contains many inner objects, and the loop may end prematurely at the END_OBJECT of an inner object.
What I thought then was, maybe I could try to make the while loop end more specifically: only when it encounters the corresponding END_OBJECT of its START_OBJECT. I have looked in the Jackson docs (at JsonParser and JsonToken) but I cannot figure out how I would do this programmatically.
My question then is, how do I write a while loop that loops through one object only? How do I uniquely define the end of the object? I thought about storing the initial start object JsonToken in memory but I am not sure how I could compare it to the end object token to see if the two are related at all. The Jackson docs aren't too descriptive on this or maybe I am too wishful and naive.
I am using a mapper because I will be doing a mix of data binding and streaming in this method. I only need to data bind the inner objects.
The first object contains an array, "decks"
The inner object contains a deck's cards (also an array).
I will be data binding single cards (as I have looked extensively but have not found an easier way to data bind inner objects (cards) while retaining some information of the "deck" they came from).
回答1:
Specifically regarding the way you do it, the simplest general solution would be counting the START_OBJECT encountered vs the END_OBJECT (same exercise in CS classes of knowing if an expression contains the correct number of opening and closing parenthesis). So your code would look like:
ObjectMapper map = new ObjectMapper(); //for later inner object data binding
JsonParser p = map.getFactory().createParser(new File("test.json"));
//start the tokenizing of object
p.nextToken();
// Assuming the first token you encounter is the START_OBJECT, otherwise start from 0.
int startEndCounter = 1;
//loop until the end object is found, simultaneously incrementing loop
while (startEndCounter != 0) {
//...
if (p.nextToken() == JsonToken.STAR_OBJECT) {
startEndCounter++;
} else if (p.nextToken() == JsonToken.END_OBJECT) {
startEndCounter--;
}
}
p.close();
And the Jackson way to read an object using the parser:
Card card = mapper.readValue(jp, Card.class);
Here's a variation of an example from the fasterxml wiki, which will read a Card object on each iteration:
JsonParser jp = map.getFactory().createParser(new File("test.json"));
// advance stream to START_ARRAY first:
jp.nextToken();
// and then each time, advance to opening START_OBJECT
while (jp.nextToken() == JsonToken.START_OBJECT)) {
Card card = mapper.readValue(jp, Card.class);
// process
// after binding, stream points to closing END_OBJECT
}
回答2:
If you reach the end of the stream, call to parser.nextToken() will return null. You can iterate until null is returned like so and build your desired object:
Object myObject;
List<Object> myObjects = new ArrayList()
JsonToken nextToken = parser.nextToken()
while (nextToken != null) {
nextToken = parser.nextToken()
if (nextToken == JsonToken.START_OBJECT) {myObject = new Object()}
else if (nextToken == JsonToken.END_OBJECT){myObjects.add(myObject)}
else {
if(parser.currentName == "myProperty"){
parser.nextToken()
myObject.property = parser.getValue()
}
}
来源:https://stackoverflow.com/questions/25425939/using-the-jackson-streaming-api-for-json-how-do-i-while-loop-through-an-object