How to parse JSON with Jackson2 when Object-Key is random? - java

I want to parse a JSON in Java with Jackson2 which has the the following structure:
{
"attachment": {
"_2K26Z-mLJmMSRnssLwD0zQ": {
"ext": "jpg",
"height": 3024,
"md5": "219c226e0070b7367f90e2f1bff1dfc2",
"name": "IMG_1871.jpg",
"ref": "MTUyMTAzNDY5MDUzNElNR18xODcxLmpwZw==",
"rotate": true,
"size": 1514957,
"thumb": "thumb_1024_219c226e0070b7367f90e2f1bff1dfc2",
"thumb_size": 73119,
"type": "image",
"width": 4032
},
"_Q7l14s87UquHcAYoolNCuw": {
"ext": "png",
"height": 186,
"md5": "75023fd60d59907376943bf109858336",
"name": "ns_attach_image_26071520280535225.png",
"ref": "MTUyMDI4MDUzNTIzMG5zX2F0dGFjaF9pbWFnZV8yNjA3MTUyMDI4MDUzNTIyNS5wbmc=",
"rotate": true,
"size": 15182,
"type": "image",
"width": 347
}
},
"title": "Test Title"
}
My problem is that I do not know how to handle the key of the attachments, because I can not define a class with the field with unknown name.
What works is
ObjectMapper mapper = new ObjectMapper();
Note note = mapper.readValue(fileio, Note.class);
where the class Note is
public class Note {
private String title;
private Object attachment;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Object getAttachment() {
return attachment;
}
public void setAttachment(Object attachment) {
this.attachment = attachment;
}
}
But I'd like to use an class with Name Attachment which holds all the fields in the json with the key "_2K26Z-mLJmMSRnssLwD0zQ".

You can use a Map, so that a key of an attachment would be a key in the map, and value in the map would be an object representing fields of the attachment. Like this:
public class Attachment {
private String ext;
private int height;
private String md5;
private String name;
private String ref;
private boolean rotate;
private int size;
private String thumb;
private int thumb_size;
private String type;
private int width;
}
public class Note {
private String title;
private Map<String, Attachment> attachment = new HashMap<>();
}

Related

How to get data from retrofit when data is like this as given below

When I try to get name while parsing the response from the server, I am getting null. Can u please help me to get data i.e, name, email and keyskills.name?
The JSON response is here.
{
"freelancer": {
"id": 3,
"name": "trinadh",
"title": "web developer",
"email": "trinadh_freelancer#gmail.com",
"gender": "Male",
"dob": "2018-09-27",
"website": "www.trinadh_freelancer.com",
"country": "India",
"state": "Karnataka",
"city": "Bangalore",
"user_id": 52,
"user_role": "freelancer",
"registered": null,
"agreement": true,
"address": "hsr layout",
"qualification": "b.tech",
"total_experience": "2",
"prefered_location": "",
"category": "Web Development",
"pancard_number": "ajhfvbqjhe",
"passport_number": "hbhfjdhbjfh",
"country_code": null,
"contact_number": "8765456721",
"currency_type": "INR",
"rate": "678.0",
"rate_card_type": "per_hour",
"negotiable": true,
"taxes": "Taxes Excluded",
"key_skills": {
"name": "ruby",
"relevant_experience": "2"
},
"other_skills": {
"name": "animation",
"relevant_experience": "3"
},
"confirmed_at": "24-Sep-2018",
"free_trail_days_left": 83,
"renewal_date": "24-Mar-2019",
"image": "<img src=\"\" />"
}
}
Here is my pojo class
public class FreeLancer {
private List<FreeLancerProfile> freelancer;
// Constructors, getters and setters are removed for convenience
}
Here is my freelancer profile
public class FreeLancerProfile {
private int id;
private String name;
private String title;
private String email;
private String gender;
private String dob;
private String website;
private String country;
private String state;
private String city;
private int user_id;
private String user_role;
private String registered;
private String agreement;
private String address;
private String qualification;
private String total_experience;
private String prefered_location;
private String category;
private String pancard_number;
private String passport_number;
private String country_code;
private String contact_number;
private String currency_type;
private String rate;
private String rate_card_type;
private String negotiable;
private String taxes;
private List<KeySkill> key_skills;
private List<OtherSkill> other_skills;
private String confirmed_at;
private String free_trail_days_left;
private String renewal_date;
private String image;
// Constructors, getters and setters are removed for convenience
}
My Pojo class for key skills
public class KeySkill {
private int id;
private String name;
private String relevant_experience;
// Constructors, getters and setters are removed for convenience
}
My Interface
public interface FreeLancerMainApi {
#GET("{fullUrl}/profile")
Call<FreeLancerProfile> freeLancerMain(
#Path(value = "fullUrl", encoded = true) String fullUrl,
#Header("Authorization") String token
);
#GET("{fullUrl}/profile")
Call<KeySkill> keySkillsMain(
#Path(value = "fullUrl", encoded = true) String fullUrl,
#Header("Authorization") String token
);
}
My Main Avtivity
String BASE_URL = "http://74.207.233.160/api/v1/freelancers/";
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
final FreeLancerMainApi api = retrofit.create(FreeLancerMainApi.class);
Call<FreeLancerProfile> call = api.freeLancerMain(freelancer_id, token);
call.enqueue(new Callback<FreeLancerProfile>() {
#Override
public void onResponse(Call<FreeLancerProfile> call, Response<FreeLancerProfile> response) {
if (response.code() == 200)
{
name = response.body().getName();
email = response.body().getEmail();
contactNumber = response.body().getContact_number();
Toast.makeText(FreelancerActivity.this, name, Toast.LENGTH_SHORT).show();
}
else {
}
}
#Override
public void onFailure(Call<FreeLancerProfile> call, Throwable t) {
}
});
Call<KeySkill> call1 = api.keySkillsMain(freelancer_id, token);
call1.enqueue(new Callback<KeySkill>() {
#Override
public void onResponse(Call<KeySkill> call, Response<KeySkill> response) {
if (response.code() == 200){
skills = response.body().getName();
}else {
}
}
#Override
public void onFailure(Call<KeySkill> call, Throwable t) {
}
});
freeLancerMainName.setText(name);
freeLancerMainEmail.setText(email);
freeLancerContactNumber.setText(contactNumber);
freeLancerKeySkills.setText(skills);
I am getting null response as when I execute this code. Please help and thanks in advance!
As I can see from the response, it is not returning an array or a list. However, as far as I have understood from your code, you are expecting to parse the response into a list.
The Freelancer pojo should look like the following.
public class FreeLancer {
public FreeLancerProfile freelancer;
}
If everything else is okay, it should work fine.
UPDATE:
The response should be bound to FreeLancer class, not to FreeLancerProfile class. I have shown an example, which might help. Please check.
public void onResponse(Call<FreeLancer> call, Response<FreeLancer> response) {
if (response.code() == 200) {
FreeLancer freelancer = response.body();
name = freelancer.getName();
email = freelancer.getEmail();
// Others ...
}
}
And in your FreelancerProfile pojo, you need to remove the List from the key_skills and other_skills as well. These are not lists as well.
private KeySkill key_skills;
private OtherSkill other_skills;

Mapping JSON String to a POJO with Jackson gives null values

I am trying to read some values under "properties" of following JSON string to a POJO. But all I get is null values.
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
144.9798,
-37.743
]
},
"properties": {
"PFI": "51351644",
"EZI_ADD": "581 BELL STREET COBURG 3058",
"ROAD_NAME": "BELL",
"ROAD_TYPE": "STREET",
"LOCALITY": "COBURG",
"LGA_CODE": "316",
"STATE": "VIC",
"POSTCODE": "3058",
"ADD_CLASS": "S"
},
"id": "ADDRESS.581"
}
My POJO class
#JsonIgnoreProperties(ignoreUnknown = true)
class Property {
public Property(){}
private String EZI_ADD; // e.g., "14 FAIRWAY COURT BUNDOORA 3083"
private String STATE; // e.g., "VIC"
private String POSTCODE; // e.g., "3083"
private String LGA_CODE; // e.g., 373
private String LOCALITY; // e.g., "BUNDOORA"
private String ADD_CLASS; // e.g., "S", or "M"
private String SA1_7DIG11 = ""; // SA1 code e.g., "2120241"
public String getEZI_ADD() {
return EZI_ADD;
}
#JsonProperty("EZI_ADD")
public void setEZI_ADD(String eZI_ADD) {
EZI_ADD = eZI_ADD;
}
public String getSTATE() {
return STATE;
}
#JsonProperty("STATE")
public void setSTATE(String sTATE) {
STATE = sTATE;
}
public String getPOSTCODE() {
return POSTCODE;
}
#JsonProperty("POSTCODE")
public void setPOSTCODE(String pOSTCODE) {
POSTCODE = pOSTCODE;
}
public String getLGA_CODE() {
return LGA_CODE;
}
#JsonProperty("LGA_CODE")
public void setLGA_CODE(String lGA_CODE) {
LGA_CODE = lGA_CODE;
}
public String getLOCALITY() {
return LOCALITY;
}
#JsonProperty("LOCALITY")
public void setLOCALITY(String lOCALITY) {
LOCALITY = lOCALITY;
}
public String getADD_CLASS() {
return ADD_CLASS;
}
#JsonProperty("ADD_CLASS")
public void setADD_CLASS(String aDD_CLASS) {
ADD_CLASS = aDD_CLASS;
}
public String getSA1_7DIG11() {
return SA1_7DIG11;
}
#JsonProperty("SA1_7DIG11")
public void setSA1_7DIG11(String sA1_7DIG11) {
SA1_7DIG11 = sA1_7DIG11;
}
}
Conversion code is as follows
//Above json string
String jsonString = "{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[144.9798,-37.743]},\"properties\":{\"PFI\":\"51351644\",\"EZI_ADD\":\"581 BELL STREET COBURG 3058\",\"ROAD_NAME\":\"BELL\",\"ROAD_TYPE\":\"STREET\",\"LOCALITY\":\"COBURG\",\"LGA_CODE\":\"316\",\"STATE\":\"VIC\",\"POSTCODE\":\"3058\",\"ADD_CLASS\":\"S\"},\"id\":\"ADDRESS.581\"}";
ObjectMapper mapper = new ObjectMapper();
Property properties = mapper.readValue(jsonString, Property.class);
Output:
{
"properties": {
"EZI_ADD": null,
"STATE": null,
"POSTCODE": null,
"LGA_CODE": null,
"LOCALITY": null,
"ADD_CLASS": null,
"SA1_7DIG11": ""
}
}
The JSON String you're sending does not match the Property class. Add a wrapper class, e.g. something like this:
public class Feature {
private String type;
private String id;
private Property property;
// getters and setters
}
Then you can send the request and the JSON String will be parsed to your object:
{
"type": "feature",
"id": "test",
"property": {
"PFI": "51351644",
"EZI_ADD": "581 BELL STREET COBURG 3058",
"ROAD_NAME": "BELL",
"ROAD_TYPE": "STREET",
"LOCALITY": "COBURG",
"LGA_CODE": "316",
"STATE": "VIC",
"POSTCODE": "3058",
"ADD_CLASS": "S"
}
}

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.

Android - Deserialize this JSON to a POJO

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

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