Parsing JSON into Jackson using a stream/object approach

12,388

To do this, you need to use an object mapper with your factory

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
...
private static ObjectMapper mapper = new ObjectMapper();
private static JsonFactory factory = mapper.getJsonFactory();

Then create a parser for the input.

JsonParser parser = factory.createJsonParser(in);

Now you can mix calls to parser.nextToken() and calls to parser.readValueAs(Class c). Here is an example that gets the classes from a map:

Map<String, Class<?>> classMap = new HashMap<String, Class<?>>();
classMap.put("dog", Dog.class);
classMap.put("person", Person.class);

InputStream in = null;
JsonParser parser = null;
List<Object> results = new ArrayList<Object>();
try {
  in = this.getClass().getResourceAsStream("input.json");
  parser = factory.createJsonParser(in);
  parser.nextToken();// JsonToken.START_OBJECT
  JsonToken token = null;
  while( (token = parser.nextToken()) == JsonToken.FIELD_NAME ) {
    String name = parser.getText();
    parser.nextToken(); // JsonToken.START_OBJECT
    results.add(parser.readValueAs(classMap.get(name)));
  }
  // ASSERT: token = JsonToken.END_OBJECT
}
finally {
  IOUtils.closeQuietly(in);
  try {
    parser.close();
  }
  catch( Exception e ) {}
}
Share:
12,388
Anonymous Person
Author by

Anonymous Person

Updated on July 19, 2022

Comments

  • Anonymous Person
    Anonymous Person almost 2 years

    I have a JSON file which can have multiple types.

    For example:

    {
        "dog": {
            "owner" : "John Smith",
            "name" : "Rex",
            "toys" : {
                "chewtoy" : "5",
                "bone" : "1"
            }
        },
        "person": {
            "name" : "John Doe",
            "address" : "23 Somewhere Lane"
        }
        // Further examples of dogs and people, and a few other types.
    }
    

    I want to parse these into objects. ie. I want to create a Dog object with owner/name/toys attributes, and person with name/address attributes, and use Jackson to read through and create objects out of them.

    The ordering matters - I need to know that Rex came before John Doe, for example. I would prefer to do with a stream like approach (ie. read and parse Rex into the Dog object, do something with it, then discard it, then move onto to John Doe). So I need a stream based approach.

    I can't figure out how to use both the stream reading API (to go through in order) and the ObjectMapper interface (in order to create Java objects out of JSON) to accomplish this.

  • Anonymous Person
    Anonymous Person over 11 years
    I think I see now. When I was trying to do that initially, I was struggling because I wouldn't know what object I was at ("dog" or "person"), but if the data is formatted as an array with the dog/person values as values in a "type" attribute, I'd be able to do this. Thanks everyone.
  • Manu Manjunath
    Manu Manjunath about 7 years
    A good answer. But, it would be great if you can rewrite your code snippet using latest Jackson library.