Mapping JSON data to Java POJO Class with Jackson Mapper
You don't need the @JsonRootName
annotation. You can just read the tree and get the users array. Then iterate through and use ObjectMapper
's readValue(JsonNode node, Class<T> class)
on each node.
Note that the capitalised ID in your json requires a hint to the parser, hence the @JsonProperty(value="ID")
annotation on the getter.
public class JacksonJSON {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(JacksonJSON.class.getResourceAsStream("/users.json"));
ArrayNode users = (ArrayNode) root.path("users");
Iterator<JsonNode> iterator = users.getElements();
while (iterator.hasNext()) {
User user = mapper.readValue(iterator.next(), User.class);
System.out.println("User id=" + user.id + " data1=" + user.data1 + " data2=" + user.data2);
}
}
}
class User {
String id;
String data1;
String data2;
@JsonProperty(value="ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getData1() {
return data1;
}
public void setData1(String data1) {
this.data1 = data1;
}
public String getData2() {
return data2;
}
public void setData2(String data2) {
this.data2 = data2;
}
}
user723858
Updated on September 07, 2020Comments
-
user723858 over 3 years
I am developing an android application and I am trying to implement the processing of some Java data using the Stream capabilities of Jackson. To do this I have a few code example to run through and will explain what each does as I go.
Here is the JSON I am working with:
{ "users": [ { "ID": "26", "data1": "Momonth", "data2": "2011-10-30 04:34:53" }, { "ID": "45", "data1": "Porto", "data2": "2011-10-18 05:34:00" }, { "ID": "21", "data1": "Tomson", "data2": "2011-10-12 02:44:13" } ], "success": 1, }
The code below is the POJO where this data will be stored as it iterates through each of the "users" array list items in my data:
@JsonRootName(value = "users") public class User { String ID; String data1; String data2; ... public String getID() { return ID; } public void setID(String iD) { ID = iD; } public String getData1() { return data1; } public void setData1(String data1) { this.data1 = data1; } public String getData2() { return data2; } public void setData2(String data2) { this.data2 = data2; } ... }
Now the code below I would expect to look at the JSON data and then grab the "users" array list of objects, I then for now wanted to simply print the name of each user to the LogCat to review that it works and as explained earlier I am looking to use the "" method as the data is quite large and I want to avoid memory issues.
HttpRequest request = HttpRequest.get("http://www.site.com/android/app/getAllUsers.php"); final Reader reader = request.reader(); final ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); final JsonFactory factory = mapper.getFactory(); try { JsonParser jp = factory.createParser(reader); while(jp.nextToken() == JsonToken.START_OBJECT) { String fieldName = jp.getCurrentName(); jp.nextToken(); final User a = mapper.readValue(jp.getText(), User.class); } } catch (JsonParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }
However the code above doesn't work in its current state and I get the following errors from Jackson:
09-06 11:11:25.326: W/System.err(15029): com.fasterxml.jackson.databind.JsonMappingException: Current token not START_OBJECT (needed to unwrap root name 'users'), but FIELD_NAME 09-06 11:11:25.326: W/System.err(15029): at [Source: java.io.InputStreamReader@432b1580; line: 1, column: 2] 09-06 11:11:25.326: W/System.err(15029): at com.fasterxml.jackson.databind.ObjectMapper._unwrapAndDeserialize(ObjectMapper.java:2948) 09-06 11:11:25.326: W/System.err(15029): at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:2858) 09-06 11:11:25.326: W/System.err(15029): at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1569) 09-06 11:11:25.326: W/System.err(15029): at com.app.tool.UsersListActivity$LoadAllUsers.doInBackground(UsersListActivity.java:381) 09-06 11:11:25.326: W/System.err(15029): at com.app.tool.UsersListActivity$LoadAllUsers.doInBackground(UsersListActivity.java:1) 09-06 11:11:25.326: W/System.err(15029): at android.os.AsyncTask$2.call(AsyncTask.java:287) 09-06 11:11:25.326: W/System.err(15029): at java.util.concurrent.FutureTask.run(FutureTask.java:234) 09-06 11:11:25.326: W/System.err(15029): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 09-06 11:11:25.326: W/System.err(15029): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 09-06 11:11:25.326: W/System.err(15029): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 09-06 11:11:25.326: W/System.err(15029): at java.lang.Thread.run(Thread.java:856)
I would really appreciate any help that can be given on this as I am stuck and cant go forward.
Thanks in advance
******EDIT********
Thanks for the reply and I have tried to implement the code however it still doesn't seem to work, the code I have now is below:
protected String doInBackground(String... args) { HttpRequest request = HttpRequest.get("http://www.site.com/android/app/getAllUsers.php"); final Reader reader = request.reader(); final ObjectMapper mapper = new ObjectMapper(); final JsonFactory factory = mapper.getFactory(); try { JsonParser jp = factory.createParser(reader); JsonNode root = mapper.readTree(jp); ArrayNode users = (ArrayNode) root.path("users"); Iterator<JsonNode> iterator = users.elements(); while (iterator.hasNext()) { User user = mapper.readValue(iterator.next(), User.class); System.out.println("User Name = " + user.data1); } } catch (JsonParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } return null; }
Do you think it has anything to do with my process running in an ASYNC task or that I am accessing my JSON through a web service? The error I get is below along with the line that it shows on:
Error Line:
User user = mapper.readValue(iterator.next(), User.class);
Error Code:
The method readValue(JsonParser, Class<T>) in the type ObjectMapper is not applicable for the arguments (JsonNode, Class<User>)
Hopefully you can help me sort this last issue out, thanks again for the assistance.