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.
Read Object From JSON via URL ObjectMapper objectMapper = new ObjectMapper(); URL url = new URL("file:data/car. json"); Car car = objectMapper. readValue(url, Car. class);
Reading JSON from a File Thankfully, Jackson makes this task as easy as the last one, we just provide the File to the readValue() method: final ObjectMapper objectMapper = new ObjectMapper(); List<Language> langList = objectMapper. readValue( new File("langs. json"), new TypeReference<List<Language>>(){}); langList.
A JsonNode is Jackson's tree model for JSON and it can read JSON into a JsonNode instance and write a JsonNode out to JSON. To read JSON into a JsonNode with Jackson by creating ObjectMapper instance and call the readValue() method. We can access a field, array or nested object using the get() method of JsonNode class.
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 ) {}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With