Deserializing child node with GSON - java

What should my POJO declaration be if I want to de-serialize the following JSON format:
{
"id":2,
"content":"skfdjhsfjhsfjkshdkjfhskdjf",
"created_at":"2012-11-14T00:10:59Z",
"feeds":
[
{
"feed":{"name":"twitter"}
}
]
}
Currently my POJOs look like that:
Broadcast.java - the outtermost object
public class Broadcast {
private String content;
private String created_at;
private Feeds feed[];
private int id;
public Broadcast() { }
public int getId() { return id; }
public String getContent() { return content; }
public String getCreatedAt() { return created_at; }
}
Feed.java - the inner child of Broadcast which can be an array and each feed has a name attribute:
public class Feeds {
private String name;
public Feeds() {}
public String getName() {
return name;
}
}

private Feeds feed[];
should be
private Feeds[] feeds;.
Actually, the placement of [] doesn't matter, but it's recommended to be placed alongside the type as it makes it clearer to read. The issue here is with the incorrect variable name.
Also, if you take a closer look at:
"feeds":
[
{
"feed":{"name":"twitter"}
}
]
you'll notice that feeds is indeed an array, but "feed":{"name":"twitter"} represents a variable (feed) holding a key-value pair ({"name":"twitter"}), thus your Feeds class should look like:
class Feeds {
private Map<String, String> feed;
public Feeds() {}
public String getName() {
return feed.get("name");
}
}

Related

jackson serialization of nested objects

I have problem with jackson serialization of object by its interface.
I have class
class Point implements PointView {
private String id;
private String name;
public Point() {
}
public Point(String id, String name) {
this.id = id;
this.name = name;
}
#Override
public String getId() {
return id;
}
public String getName() {
return name;
}
}
which implements
interface PointView {
String getId();
}
and have class
class Map implements MapView {
private String id;
private String name;
private Point point;
public Map() {
}
public Map(String id, String name, Point point) {
this.id = id;
this.name = name;
this.point = point;
}
#Override
public String getId() {
return id;
}
public String getName() {
return name;
}
#JsonSerialize(as = PointView.class)
public Point getPoint() {
return point;
}
}
which implements
interface MapView {
String getId();
Point getPoint();
}
And have class
class Container {
private Map map;
public Container() {
}
public Container(Map map) {
this.map = map;
}
#JsonSerialize(as = MapView.class)
public Map getMap() {
return map;
}
}
I want serialize Container with Jackson and get result
{"map":{"id":"mapId","point":{"id":"pointId"}}}
But in fact I get result
{"map":{"id":"mapId","point":{"id":"pointId","name":"pointName"}}}
that have property "name" in nested object "point" although I specified serializition type of Point in Map (#JsonSerialize(as = PointView.class)). Interface PointView dont have method getName, but in result exists field "name" of Point.
If I remove annotation (#JsonSerialize(as = MapView.class)) from method getMap in class Container I get result
{"map":{"id":"mapId","name":"mapName","point":{"id":"pointId"}}}
Now point dont have property "name", but map have.
How can I get result
{"map":{"id":"mapId","point":{"id":"pointId"}}}
?
To get the desired result also the same method in interface must be annotated by #JsonSerialize
interface MapView {
String getId();
#JsonSerialize(as = PointView.class)
Point getPoint();
}
You can annotate the method like this:
#JsonIgnore
public String getName() {
return name;
}
Or if you want specific serialization in this use case, but normal serialization in others, you can use a #JsonView (see doc).
The reason it's serializing out the name is that the instance has the accessor getName(), even though interface does not.
Yes, you can use
#JsonSerialize(as=MyInterface.class)
public class ConcreteClass implements MyInterface { .... }
either on implementation class (as above), or on property that has value.

How to write a generic getObject() method for json string?

Got into a very basic issue. I have to convert json string to objects. I have a custom method as below which is expected to convert into corresponding class and throw an exception if it is not able to get the object out of it.
protected <T> T getObjectFromJson(Class<T> c, String json){
try{
Gson gson = new Gson();
T object = gson.fromJson(json, c);
return object;
} catch (Exception e){
throw new TMMIDClassConversionException(e.getCause(), e.getMessage());
}
}
The issue is this method is not throwing exception if I am trying to convert json of a different class.
My class
public class CompanyCategoryMap {
private Integer id;
private int mid;
private String catKey;
private String catValue;
private int priority;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
public String getCatKey() {
return catKey;
}
public void setCatKey(String catKey) {
this.catKey = catKey;
}
public String getCatValue() {
return catValue;
}
public void setCatValue(String catValue) {
this.catValue = catValue;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
}
When I pass json string of Company rather than String of above class, it does not throw exception.
The string:
"{\"id\":6,\"name\":\"abc\",\"usersCount\":10,\"mid\":3,\"createdAt\":\"Sep 15, 2014 7:02:19 PM\",\"updatedAt\":\"Sep 15, 2014 7:02:19 PM\",\"active\":true,\"currency\":\"abc\",\"source\":\"unknown\",\"user_id\":1,\"tierId\":1}"
I think I am doing this conversion in a wrong way. What is the suggested way of doing it?
Take for example:
class Foo {
private String value;
}
class Bar {
private String value;
}
and
String json = "{\"value\" : \"whatever\"}";
new Gson().fromJson(json, Foo.class);
new Gson().fromJson(json, Bar.class);
Why should Gson reject any of these?
Gson is setup to perform a best effort to deserialize the given JSON into an instance of the given Class. It will map as many fields as it finds. If none are found, that's too bad.
Other libraries like Jackson do the opposite. By default, Jackson rejects any JSON which doesn't contain a mapping for every given class property. You can also configure it to ignore some properties.
Keep doing what you are doing. As the application writer, you should know when to use a Class instance with the appropriate JSON source.

Deserializing JSON wrapper object with list returns null properties

I got json like below:
{"examinationTypes":[{"ExaminationTypeVO":{"id":1,"name":"Badanie krwi"}},{"ExaminationTypeVO":{"id":2,"name":"Spirometria"}},{"ExaminationTypeVO":{"id":3,"name":"Wymaz"}},{"ExaminationTypeVO":{"id":4,"name":"Ciśnienie"}},{"ExaminationTypeVO":{"id":5,"name":"EKG"}},{"ExaminationTypeVO":{"id":6,"name":"Elektrowstrząsy"}},{"ExaminationTypeVO":{"id":7,"name":"Tomografia"}},{"ExaminationTypeVO":{"id":8,"name":"Lewatywa"}},{"ExaminationTypeVO":{"id":9,"name":"Aneskopia"}},{"ExaminationTypeVO":{"id":10,"name":"Rektoskopia"}},{"ExaminationTypeVO":{"id":11,"name":"Kolonoskopioa"}},{"ExaminationTypeVO":{"id":12,"name":"Echo serca"}},{"ExaminationTypeVO":{"id":13,"name":"Ablacja"}},{"ExaminationTypeVO":{"id":14,"name":"Badnaie dopplerowskie"}},{"ExaminationTypeVO":{"id":15,"name":"Kapilaroskopia"}}]}
I have defined types:
#JsonRootName(value="ExaminationTypeVO")
#JsonIgnoreProperties(ignoreUnknown = true)
public class ExaminationTypeVO {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and
public class ExaminationTypesVO {
private List<ExaminationTypeVO> examinationTypes;
public List<ExaminationTypeVO> getExaminationTypes() {
return examinationTypes;
}
public void setExaminationTypes(List<ExaminationTypeVO> examinationTypes) {
this.examinationTypes = examinationTypes;
}
When I am deserializing it like that:
ExaminationTypesVO l = m.readValue(result, ExaminationTypesVO.class);
I receive an wrapper object but the list inside contains objects of type ExaminationTypeVO with all properties set to null.
Can anybody help to figure it out?
Your issue is that you have an extra level of object that you are trying to deserialize. Trying to not be confusing as I explain this: you have an array of objects, those objects contain a single ExaminationTypeVO object.
If you are stuck with the structure of the JSON that you provided, then you will need to add another "level" to your deserialization. You can do this via a wrapper object inside of your ExaminationTypesVO class:
public class ExaminationTypesVO {
private List<ExaminationTypeVOWrapper> examinationTypes;
public List<ExaminationTypeVOWrapper> getExaminationTypes() {
return examinationTypes;
}
public void setExaminationTypes(List<ExaminationTypeVOWrapper> examinationTypes) {
this.examinationTypes = examinationTypes;
}
public static class ExaminationTypeVOWrapper {
private final ExaminationTypeVO examinationTypeVO;
#JsonCreator
public ExaminationTypeVOWrapper(#JsonProperty("ExaminationTypeVO") ExaminationTypeVO examinationTypeVO) {
this.examinationTypeVO = examinationTypeVO;
}
public ExaminationTypeVO getExaminationTypeVO() {
return examinationTypeVO;
}
}
}
If you have control over the JSON that you are deserializing, you can just remove the extra "level" (ExaminationTypeVO wrapping object) and not have to change your code. Your new JSON in this approach would look like:
{
"examinationTypes": [
{
"id": 1,
"name": "Badanie krwi"
}, ...
]
}
With either of these approaches you can remove both of the class-level annotations you have on ExaminationTypeVO.

How to grab JSON Array and use gson to parse each json object? (Retrofit)

I am returning an array of results with my json Objects, and I am trying to use my customObjectResponse class to pull out each of the fields within each of the objects... the problem it is expecting an object so how do I edit my class to allow it to take in an array of object to be able to then call the fields of each object... I am confused as to what needs to be added:
Here is a response example of what is being passed to be used:
[
{
itemId: 'dfsdfsdf343434',
name: 'tests',
picture: '6976-7jv8h5.jpg',
description: 'testy.',
dateUpdated: 1395101819,
}
]
Here is my response Object Class:
public class ObjResponse{
private String itemId;
private String name;
private String picture;
private String description;
private String location;
private int dateUpdated;
private String msg;
//gridview constructor
public ObjResponse(String picture) {
this.picture = picture;
}
//public constructor
public ObjResponse() {
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getDateUpdated() {
return dateUpdated;
}
public void setDateUpdated(int dateUpdated) {
this.dateUpdated = dateUpdated;
}
public String getMsg() {
return msg;
}
}
what I am trying, but is not working, even if I separate the classes into their own files:
Data passed in:
items: [{obj1: "A", obj2: ["c", "d"]}, {etc...}]
public class Response {
public class List<Custom> {
private List<Custom> items;
}
public class Custom {
private String obj1;
private List<Obj2> obj2;
}
public Class Obj2 {
private String letters;
}
}
I ended up just calling in the callback a list of the customObject and it did the job...
new Callback<List<ObjResponse>>() {
I originally had trouble getting an idea of how the OP solved his problem but, after days of debugging I have finally figured out how to solve this issue.
So you essentially have data in the format like so (JSON Array of JSON Objects):
[
{
...
}
]
Your class that models the data and contains the getter and setter methods are nothing more than your typical POJO.
public class Person implements Serializable {
#SerializedName("Exact format of your json field name goes here")
private String firstName;
// Getters and Setters....
}
In your interface that contains your RESTful annotations you want to convert your call from:
Before:
public interface APInterface {
#GET("SOME URL TO YOUR JSON ARRAY")
Call<Person>(...)
}
After:
public interface APInterface {
#GET("SOME URL TO YOUR JSON ARRAY")
Call<List<Person>>(...)
}
In your android activity you want to convert all calls in the form of Call<Person> to Call<List<Person>>
Finally when making the initial asynchronous request call, you will want to convert your callbacks like so.
call.enqueue(new Callback<List<Person>>() {
#Override
public void onResponse(Call<List<Person>> call, Response<List<Person>> response) {
if(response.isSuccessful()){
List<Person> person = response.body();
// Can iterate through list and grab Getters from POJO
for(Person p: person){...}
} else {
// Error response...
}
}
#Override
public void onFailure(Call<List<Person>> call, Throwable t) {...}
});
Hope this helps others whom are lost from the accepted answer above.
This can also work by just passing an array of response objects. So if this is your response object:
public class CustomUserResponse {
public String firstName;
public String lastName;
...
}
You can use related syntax, depending on how you use the callbacks. Such as:
new Callback<CustomUserResponse[]>(){
#Override
public void success(CustomUserResponse[] customUserResponses, Response rawResponse) {
}
#Override
public void failure(RetrofitError error) {
}
};
OR
public class GetUserCommand implements Callback<CustomUserResponse[]> { ...
Put simply, in every place where you normally replace T with a response class, replace it with an array, instead as in CustomUserResponse[].
NOTE: to avoid confusing errors, be sure to also use an array in the Retrofit interface definition:
#POST ( "/users" )
public void listUsers(#Body GetUsersRequest request, Callback<CustomUserResponse[]> callback);
You could try something like this
JSONObject jsonObject = new JSONObject(<your JSON string result>);
JSONArray jsonArray = jsonObject.getJSONArray();
//use GSON to parse
if (jsonArray != null) {
Gson gson = new Gson();
ObjResponse[] objResponse = gson.fromJson(jsonArray.toString(), ObjResponse[].class);
List<ObjResponse> objResponseList = Arrays.asList(objResponse);
}
This should definitely work.

GSON parsing to object

I will be recieving JSON strings in the following format:
{ "type":"groups", "groups":[ {"group":"NAME"}, ...] }
How would one form an object so that the following would work.
MyClass p = gson.fromJson(jsonString, MyClass.class);
The part I'm stuck it is "{"group":"NAME"}". Would this be fixed by saving objects inside the an array? Example.
public class MyClass {
private String type;
private List<MyOtherClass> groups = new ArrayList<MyOtherClass>();
//getter and setter methods
}
Answer: Nesting objects in each other doh! Thanks you guys! Crystal clear now :D
public class MyOtherClass {
private String group;
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
#Override
public String toString() {
return "group: "+group;
}
}
First you need a POJO for the group:
public class MyOtherClass {
#Expose
private String group;
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
}
Next you need one for your 'MyClass', which would look like this:
public class MyClass {
#Expose
private String type;
#Expose
private List<MyOtherClass> groups = new ArrayList<MyOtherClass>();
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<Group> getGroups() {
return groups;
}
public void setGroups(List<Group> groups) {
this.groups = groups;
}
}
Hope this helps.
At first glance, this looks fine, assuming MyOtherClass has a field called group that holds a String. What do you mean by "the part I'm stuck [on]"? Perhaps you could post the stack trace you're seeing, a broader description of what you're trying to do, or best of all a SSCCE?
When using GSON, I find it easiest to implement the class structure I need, then let GSON generate the JSON data from that. You certainly can go the other way (design class structure based on JSON data), but I think it's more confusing if you don't understand what GSON is trying to do.
Some pseduo-code:
Class MyClass
String type
List<MyOtherClass> groups
Class MyOtherClass
String group
Looking at this we can easily see the JSON that will hold our serialized object will look like so:
{
type: "...",
groups: [
{ group: "..." },
...
]
}

Categories