Android - Deserialize this JSON to a POJO - java

This is my JSON:
{
"results": [
{
"user_id": "1",
"item_id": "18630",
"name": "Unnamed Item",
"price": "0",
"description": "",
"created_at": "2014-01-16 15:31:36",
"thumbnail": {
"image50": "http://www.example.com/adsa.jpg",
"image100": "hhttp://www.example.com/adsa.jpg"
},...
Am I doing the deserialization right?
public class ItemListModel {
private String user_id;
private String item_id;
private String name;
private String price;
private String category;
private ArrayList<ThumbnailResponse> thumbnail;
public ItemListModel(){}
// getters
}
public class ThumbnailResponse {
private String image50;
private String image100;
public ThumbnailResponse(){
}
//getters
}
I'm just confused, when do we use ArrayList, Array or List for array or object in the JSON file?
One more thing, do I need to make results as an array too if that's the case?

As you have given
"thumbnail": {
"image50": "http://www.example.com/adsa.jpg",
"image100": "hhttp://www.example.com/adsa.jpg"
}
is not a JsonArray. So you have no need to use ThumbnailResponse as an ArrayList into ItemListModel.
Your Model should be
public class ItemListModel {
private String user_id;
private String item_id;
private String name;
private String price;
private String category;
private ThumbnailResponse thumbnail; // Not array List
public ItemListModel(){}
// getters
}
And
One more thing, do I need to make results as an array too if that's
the case?
Your main data container should be contain ArrayList of ItemListModel. Like below
ArrayList<ItemListModel> results = new ArrayList<ItemListModel>();

[] in json -> array
{} in json -> object or map
in your case
// change
private ArrayList<ThumbnailResponse> thumbnail;
// to
private Map<String,String> thumbnail;
if you want it the way you declared your java object you need to provide a transformer (depends on the framework you are using)

List<ItemListModel > ItemListModel ;
try {
Type listType = new TypeToken<List<ItemListModel >>(){}.getType();
result= (List<ItemListModel >) gson.fromJson(result, listType);
} catch (Exception e) {
Log.e("Parsing exeption", e.getLocalizedMessage(), e);
}
this should work

Related

Retrofit - JSON Array Parsing

I am parsing JSON Array using Retrofit, where JSON Array looks like:
"hobbies": [ "Music", "Reading"]
Here is what my JSON looks like:
{
"type":"success",
"value":[
{
"id":1,
"title":"Title - 1",
"name":{
"first":"First - 1",
"last":"Last - 1"
},
"hobbies":[
"Writing Code - 1",
"Listening Music - 1"
]
},
.....
]
}
Value.java
private List<String> hobbies = new ArrayList<String>();
Adapter.java
viewHolder.hobbies.setText(value.getHobbies().toString());
And when I run my program, I am getting data as seen below:
[Music, Reading]
So, Question is Why I am getting [] as well in output.
Value.java
public class Value {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("title")
#Expose
private String title;
#SerializedName("hobbies")
#Expose
private List<String> hobbies = new ArrayList<String>();
#SerializedName("name")
#Expose
private Name name;
.....
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
}
Service.java
public interface Service {
#GET("/demo_retrofit.json")
Observable<Master> getMaster();
}
Actually value.getHobbies(); directly return an List with [ ]. better iterate it and show by using StringBuilder
MD and Jackson are right. Object.toString() method returns a string that "textually represents" this object. So for your case, hobbies is an arrayList so the textually representation will have [] with it. ;)
Edit:
You may want to use for loop for this:
for (String hobby : hobbies) {
// Do something with hobby here
}

Gson calls returns empty objects over multiple classes

I'm trying to serialize to serialize the json string I have included below.
{
"mood": {
"is_featured": true,
"description": null,
"title": "2014 ",
"ordering": null,
"is_recently_modified": true,
"is_test": false,
"tracks": [
{
"album": {
"release_date": "2014-11-06",
"id": 359778,
"name": "Amansız Gücenik"
},
"name": "Hırpalandı Mayıs",
"artist": {
"id": 491169,
"name": "Ceylan Ertem"
},
"duration": 227,
"isrc": "TRA161400207",
"id": 3903997
},
{
"album": {
"release_date": "2013-08-05",
"id": 329129,
"name": "For Fuld Musik - 25 Danske Sommer Pop & Rock Hits Vol. 2"
},
"name": "Am I Wrong",
"artist": {
"id": 755957,
"name": "Nico & Vinz"
},
"duration": 387,
"isrc": "NO2G31301011",
"id": 3655085
}
],
"image_url": "some_url",
"is_recently_created": true,
"id": 128
}
}
I'm using this gson call to serialize it
Mood mood = new Gson().fromJson(result, Mood.class);
My class structers are like this.
public class Mood {
private boolean is_featured;
private boolean is_recently_modified;
private boolean is_recently_created;
private boolean is_test;
private String description;
private String title;
private String image_url;
private int id;
private int ordering;
private Track[] tracks;
public static class MoodContainer {
public Mood[] moods;
}
}
public class Track {
//variables
private Album album;
private Artist artist;
private Provider provider;
private String secure_url;
private String name;
private String region;
private String isrc;
private int duration;
private int track_order;
private int id;
}
And it goes on like this for any additional class variable. When I try to use the above call I end up with objects that have all null values. One thing to notice is some fields are not supplied in json string because different api calls supply different parts of these json strings. What I am doing wrong?
Root JSON object you provided has property mood - so you either have two options for deserialization to work properly:
Wrap your Mood class inside another object like this:
public class MoodWrapper { private Mood mood; }
and change de-serialization code to
MoodWrapper moodWrapper = new Gson().fromJson(result, MoodWrapper.class);
Skip a root object when deserializing:
final Gson gson = new Gson();
JsonParser parser = new JsonParser();
JsonObject rootObj = parser.parse(json).getAsJsonObject();
Mood mood = gson.fromJson(rootObj.getAsJsonObject("mood"), Mood.class);
The top-level elements in the JSON string should be your object's properties, not the outer element "mood" which you have.

Parse specific JSON array using JACKSON parser

{
"response": [
{
"id": "1",
"name": "xx"
},
{
"id": "2",
"name": "yy"
}
],
"errorMsg": "",
"code": 0
}
How to parse "response" alone using jackson parser. I am getting error as
Unrecognized field "errorMsg", not marked as ignorable.
My model class Response.java
public class Response {
#JsonProperty("id")
private Integer id;
#JsonProperty("name")
private String name;
}
Your data model is a bit incomplete and this is what Jackson is pointing out.
To improve the situation you should map more fields.
public class Response {
#JsonProperty("id")
private Integer id;
#JsonProperty("name")
private String name;
// getter/setter...
}
public class Data {
#JsonProperty("response")
private List<Response> response;
#JsonProperty("errorMsg")
private String errorMsg;
#JsonProperty("code")
private int code;
// getter/setter...
}
You can either create a parent object and use #JsonIgnoreProperties. Alternatievly you could get the node and convert it to response object using ObjectMapper's convertValue() method like
try {
String json = "{\"response\":[{\"id\":\"1\",\"name\":\"xx\"},{\"id\":\"2\",\"name\":\"yy\"}],\"errorMsg\":\"\",\"code\":0}";
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(json);
List<Response> responses = mapper.convertValue(node.findValues("response").get(0), new TypeReference<List<Response>>() {});
System.out.println(responses);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

GSON custom object deserialisation setting all fields to null

I am using GSON for the first time. I am trying to deserialise a JSON string into a custom object, but every property of my object is set to null. There are no parsing errors so I think the JSON properties are not mapping to the object?
Here is my code, if anyone could point out where I have gone wrong it would be much appreciated. I have checked everything against tutorial and cannot see the problem. The only thing is that there are more properties in the JSON string than in my object but I hope that does not matter.
JSON string:
{
"_id": "D7D4A7D8219CA25848257C63000A1B50",
"ReportingPerson": "TRAIN2 Ifap",
"InjuredPerson": "TRAIN3 Ifap",
"DateReported": {
"$date": "2014-01-17T00:00:00.000Z"
},
"Company": "test",
"Division": "Learning & Development",
"Site_id": "3CA9AD4E6066388648257B7500047D90",
"Department_id": "724BC4B509E7B61648257363002FD645",
"Area": "Training Room",
"DocNo": "002223",
"CreatedBy": "Ifap TRAIN2",
"DateComposed": {
"$date": "2014-01-17T01:50:23.000Z"
},
"OccurTime": "12:00:00",
"Affiliation": "Employee",
"BriefDescription": "Employee tripped over power lead in computer lab.",
"ThirdPartyInvolvedYN": "No",
"ThirdPartyName": "",
"ThirdPartyAddress": [
""
],
"ThirdPartyTel": "",
"Classification": "Minor Injury",
"Confidential": "",
"ConfidentialMonitors": [
""
],
"IncidentCategory": "2",
"IncidentCategoryPotential": "3",
"ReportableYN": "No",
"ExternalBody": [
""
],
"Authorisor": "",
"WorkSafeConfirmedYN": "No",
"Details": "Fell over cord in computer lab when walking through. Held hand out to brace fall and fell on pinkie finger.",
"Controls": [
"Tape over cord."
],
"Witnesses": [
"No"
],
"Supervisor": "TRAIN1 Ifap",
"IntAuthorisor": "TRAIN3 Ifap",
"IntAuthorisorNext": "",
"AssociatedRisks": {},
"OpenActions": {},
"ClosedActions": {}
}
POJO:
public class Incident {
#SerializedName("_id")
private String _id;
private String docNo;
private String site_id;
private String company;
private String division;
private String department_id;
private Date dateReported;
private String briefDescription;
private String thirdPartyInvolvedYN;
private String supervisor;
private String classification;
private String status;
private String injuredPerson;
private String reportingPerson;
private Date occurDate;
private String occurTime;
//Getters & Setters...
}
Main method:
public Incident convertJSONToBean(String json) {
Incident i = new Incident();
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
Type type = new TypeToken<Incident>(){}.getType();
try {
i = gson.fromJson(json, type);
} catch (JsonSyntaxException e) {
e.printStackTrace();
} catch (JsonIOException e) {
e.printStackTrace();
}
return i;
}
Type is set correctly to Incident.class. But any properties of the resulting Incident object are all null.
I tried commenting out all properties except _id to see if I could get just one to populate but it was still set to null.
In Json format DateComposed & DateReported properties are the Object, You need to create the
either custom model classes for them or write CustomDeserializer class for them.
"DateComposed": { "$date": "2014-01-17T01:50:23.000Z" }
"DateReported": {"$date": "2014-01-17T00:00:00.000Z"}
public class Incident {
#SerializedName("_id")
private String _id;
#SerializedName(value = "ReportingPerson")
// other properties, you need to put #SerializedName on each property
............
// No need to put SerializedName annotation on dateReported & dateComposed
private Date dateReported;
private Date dateComposed;
#SerializedName(value = "ThirdPartyAddress")
private List<String> thirdPartyAddress;
#SerializedName(value = "ConfidentialMonitors")
private List<String> confidentialMonitors;
#SerializedName(value = "ExternalBody")
private List<String> externalBody;
#SerializedName(value = "Controls")
private List<String> controls;
#SerializedName(value = "Witnesses")
private List<String> witnesses;
// getter/setter
....
}
Here is the CustomDeserializer class for Deserializing date properties
public class CustomDeserializer implements JsonDeserializer<Incident> {
#Override
public Incident deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
final JsonObject jsonObject = json.getAsJsonObject();
final Gson gson = new Gson();
// Parse the JsonElement tree here
final Incident incident = gson.fromJson(json, Incident.class);
// getting date properties as string from JsonElement and parse them into date object.
String dateReportedStr = jsonObject.get("DateReported").getAsJsonObject().get("$date").getAsString();
String dateComposedStr = jsonObject.get("DateComposed").getAsJsonObject().get("$date").getAsString();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
try {
// setting date properties in incident object
incident.setDateReported(df.parse(dateReportedStr));
incident.setDateComposed(df.parse(dateComposedStr));
} catch (ParseException e) {
e.printStackTrace();
}
return incident;
}
}
Finally Parse it
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Incident.class, new CustomDeserializer());
Gson gson = gsonBuilder.create();
Incident incident = gson.fromJson(Your_JSON_STR, Incident.class);
You have interesting date objects in your json string. Such as;
"DateReported": {
"$date": "2014-01-17T00:00:00.000Z"
}
Which causes a JsonParseException because of your Incident class:
com.google.gson.JsonParseException: The date should be a string value
For your Incident class, Dates at json value should be something like;
"DateReported": "2014-01-17T00:00:00.000Z"
If you don't have an option to change dates at json value, then you should define its custom date holder class:
public class CustomDateHolder {
#SerializedName("$date")
private Date date;
// Getters & Setters...
}
And change those date fields' type to CustomDateHolder;
public class Incident {
#SerializedName("_id")
private String _id;
private String docNo;
private String site_id;
private String company;
private String division;
private String department_id;
private CustomDateHolder dateReported;
private String briefDescription;
private String thirdPartyInvolvedYN;
private String supervisor;
private String classification;
private String status;
private String injuredPerson;
private String reportingPerson;
private CustomDateHolder occurDate;
private String occurTime;
// Getters & Setters...
}
Also modify your GsonBuilder a little bit:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);
gsonBuilder.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Gson gson = gsonBuilder.create();

Creating a listview from a nested JSON

I have a JSON file that I fetch from the internet which contains schedule data for a TV channel. Nested within that file, alongside lots of metadata, is info about each broadcast (i.e. each programme) and below is a sample of that file:
For ease of understanding, I recommend this visual representation of the below JSON instead (click on the Viewer tab on the JSON viewer).
{
"schedule": {
"service": {
"type": "tv",
"key": "bbcnews",
"title": "BBC News Channel"
},
"day": {
"date": "2013-11-15",
"has_next": 1,
"has_previous": 1,
"broadcasts": [
{
"is_repeat": false, <=== This is the 1st broadcast programme
"is_blanked": false,
"pid": "p01ks4z3",
"start": "2013-11-15T03:45:00Z",
"end": "2013-11-15T04:00:00Z",
"duration": 900,
"programme": {
"type": "episode",
"pid": "b03hdhhp",
"position": null,
"title": "15/11/2013",
"short_synopsis": "All the latest sports news and results from around the globe.",
"media_type": "audio_video",
"duration": 900,
"display_titles": {
"title": "Sport Today",
"subtitle": "15/11/2013"
},
"first_broadcast_date": "2013-11-15T03:45:00Z",
"ownership": {
"service": {
"type": "tv",
"id": "bbc_news24",
"key": "bbcnews",
"title": "BBC News Channel"
}
},
"programme": {
"type": "brand",
"pid": "b0121xvw",
"title": "Sport Today",
"position": null,
"expected_child_count": null,
"first_broadcast_date": "2011-06-13T02:45:00+01:00",
"ownership": {
"service": {
"type": "tv",
"id": "bbc_news24",
"key": "bbcnews",
"title": "BBC News Channel"
}
}
},
"is_available_mediaset_pc_sd": false,
"is_legacy_media": false
}
},
{
"is_repeat": false, <=== This is the 2nd broadcast programme
"is_blanked": false,
"pid": "p01ks4z4",
"start": "2013-11-15T04:00:00Z",
"end": "2013-11-15T04:30:00Z",
"duration": 1800,
"programme": {
"type": "episode",
"pid": "b03hdhhs",
"position": null,
"title": "15/11/2013",
"short_synopsis": "Twenty-four hours a day, the latest national and international stories as they break.",
"media_type": "audio_video",
"duration": 1800,
"display_titles": {
"title": "BBC News",
"subtitle": "15/11/2013"
},
"first_broadcast_date": "2013-11-15T04:00:00Z",
"ownership": {
"service": {
"type": "tv",
"id": "bbc_news24",
"key": "bbcnews",
"title": "BBC News Channel"
}
},
"programme": {
"type": "brand",
"pid": "b006mgyl",
"title": "BBC News",
"position": null,
"expected_child_count": null,
"first_broadcast_date": "2006-11-01T13:00:00Z",
"ownership": {
"service": {
"type": "tv",
"id": "bbc_news24",
"key": "bbcnews",
"title": "BBC News Channel"
}
}
},
"is_available_mediaset_pc_sd": false,
"is_legacy_media": false
}
}
]
}
}
}
Using the answer to this question on StackOverflow, I created a Javabean class like so:
private class ScheduleData {
private Schedule schedule;
// create getter & setter
public static class Schedule {
private Service service;
private Day day;
// create getter & setter
}
public static class Service {
private String type;
private String key;
private String title;
// create getter & setter
}
public static class Day {
private String date;
private String has_next;
private String has_previous;
private Broadcasts broadcasts;
// create getter & setter
}
public static class Broadcasts {
private String is_repeat;
private String is_blanked;
private String pid;
private String time;
private String end;
private String duration;
private OuterProgramme programme;
// create getter & setter
}
public static class OuterProgramme {
private String type;
private String pid;
private String position;
private String title;
private String short_synopsis;
private String media_type;
private String duration;
private String first_broadcast_date;
private DisplayTitles display_titles;
private Ownership ownership;
private InnerProgramme programme;
// create getter & setter
}
public static class DisplayTitles {
private String title;
private String subtitle;
// create getter & setter
}
public static class Ownership {
private Service service;
// create getter & setter
}
public static class Service {
private String type;
private String id;
private String key;
private String title;
// create getter & setter
}
public static class InnerProgramme {
private String type;
private String pid;
private String title;
private String position;
private String expected_child_count;
private String first_broadcast_date;
private Ownership ownership;
private String is_available_mediaset_pc_sd;
private String is_legacy_media;
// create getter & setter
}
}
In my activity file, how do I loop through each broadcast node of the fetched JSON and retrieve programme data such as short_synopsis or display_titles and pass these into a custom listview display?
1) Define root Json Wrapper class ScheduleData.java
public class ScheduleData {
private Schedule schedule;
public Schedule getSchedule() {
return schedule;
}
}
2) Define its properties as seperate public classes:
2.a) Schedule.java
public class Schedule {
private Service service;
private Day day;
// TODO: create other getters & setters if you need
public Day getDay() {
return day;
}
}
2.b) Service.java
public class Service {
private String type;
private String id;
private String key;
private String title;
// TODO: create getters & setters if you need
}
2.c) Day.java
public class Day {
private String date;
private int has_next;
private int has_previous;
private Broadcast[] broadcasts;
// TODO: create other getters & setters if you need
public Broadcast[] getBroadcasts() {
return broadcasts;
}
}
2.d) Broadcast.java
public class Broadcast {
private boolean is_repeat;
private boolean is_blanked;
private String pid;
private String start;
private String end;
private int duration;
private Programme programme;
// TODO: create other getters & setters if you need
public Programme getProgramme() {
return programme;
}
}
2.e) Programme.java
public class Programme {
private String type;
private String pid;
private String position;
private String title;
private String short_synopsis;
private String media_type;
private int duration;
private String first_broadcast_date;
private DisplayTitle display_titles;
private Ownership ownership;
private Programme programme;
// TODO: create other getters & setters if you need
public String getShort_synopsis() {
return short_synopsis;
}
public DisplayTitle getDisplay_titles() {
return display_titles;
}
}
2.f) DisplayTitle.java
public class DisplayTitle {
private String title;
private String subtitle;
// create getter & setter
}
2.g) Ownership.java
public class Ownership {
private Service service;
// create getter & setter
}
3) Define an AsyncTask and call json service. Get result as stream and set its value to a ScheduleData instance using gson library. (I assume you know how to call json service on android, but if you don't it is a 5 min googling issue.)
HttpEntity getResponseEntity = getResponse.getEntity();
InputStream source = getResponseEntity.getContent();
Gson gson = new Gson();
Reader reader = new InputStreamReader(source);
ScheduleData scheduleData = gson.fromJson(reader, ScheduleData.class);
4) Now you have a ScheduleData instance. It is filled by service's json response.
Schedule schedule = scheduleData.getSchedule();
Day day = schedule.getDay();
Broadcast[] broadCastArr = day.getBroadcasts();
// TODO: use your broadCastArr in an adapter

Categories