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

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.

Related

How can i convert convert json to object with different field names GSON

how can i convert this json:
[{"id":"0","value":1010},{"id":"1","value":"1000"},{"id":"2","value":"1111"}]
to single object having object having fields.
value0;(corresponds to id of value 0) it should be 1010
value1;(corresponds to id of value 1) it should be 1000
value2;(corresponds to id of value 2)
using GSON how can i implement it.
Create a Java Class according to your json object field like:-
public class Example {
private String id;
private String value;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
And one more class to represent arrays of json value to JAVA objects:-
public class JSONExample {
List<Example> examples;
public List<Example> getExamples() {
return examples;
}
public void setExamples(List<Example> examples) {
this.examples = examples;
}
}
Then you can loop your JSON object/array to create "Example" java
Object and using the same create JSONExample object.
Thats It.
It is going to be something like below :
String yourJson = "[{"id":"0","value":1010},{"id":"1","value":"1000"},{"id":"2","value":"1111"}]";
Gson gson = new Gson();
YourObject[] yourObjectArr= gson.fromJson(yourJson, YourObject[].class);
class YourObject
{
String id;
String value;
}

How to set entire enum list in a variable and then save it in MongoDB

I need to save Enum data in MongoDB, for this I am able to get the Enum data but not getting how to set it. I am using Enum in a POJO and need to save that POJO containing Enum in MongoDB, used Gson for this.
import javax.annotation.Generated;
#Generated("org.jsonschema2pojo")
public class Coverage1 {
public enum Coverage {
Hearing_Aid_Professional_Liability("HEAR"), Incidental_Motorized_Land_Conveyances_Liability_Only("LANDC"), PremisesOperations_334("PREM"), Rental_Reimbursement("RREIM"), Liquor_Law_Liability_332("LLL"), Wind("WIND"), Business_Personal_Property("BPP"), OpticianOptometrists_Professional_Liability("OOPRL"), Builders_Risk("BLDRK"), Incidental_Farming_Personal_Liability("IFPL");
private String val;
Coverage(String val){
this.val = val;
}
public String getVal ()
{
return this.val;
}
public void setVal (String val)
{
this.val = val;
}
}
public Coverage value;
public Coverage getValue() {
return value;
}
public void setValue(Coverage value) {
this.value = value;
}
private String id;
private CoverageCd coverageCd;
private CoverageDesc coverageDesc;
private CoverageTypeCd coverageTypeCd;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public CoverageCd getCoverageCd() {
return coverageCd;
}
public void setCoverageCd(CoverageCd coverageCd) {
this.coverageCd = coverageCd;
}
public CoverageDesc getCoverageDesc() {
return coverageDesc;
}
public void setCoverageDesc(CoverageDesc coverageDesc) {
this.coverageDesc = coverageDesc;
}*
public CoverageTypeCd getCoverageTypeCd() {
return coverageTypeCd;
}
public void setCoverageTypeCd(CoverageTypeCd coverageTypeCd) {
this.coverageTypeCd = coverageTypeCd;
}
}
In another class I am calling it from where i need to save it in Mongo DB.
Coverage1 cv= new Coverage1();
List<Coverage1.Coverage> ae= new ArrayList<Coverage1.Coverage>();
for(Coverage1.Coverage enumval:Coverage1.Coverage.values()){
//ae=enumval;
System.out.println(enumval);
cv.setValue(enumval);//I need to set the entire Enum data here, so that it could be saved in Mongo. But not getting how to save the entire data
}
cv.setId("1");
Gson gson = new Gson();
String json = gson.toJson(cv);
System.out.println(json);
// Parse to bson document and insert
Document doc = Document.parse(json);
db.getCollection("NameColl").insertOne(doc);
Please someone help me how to save the entire Enum data in Mongo document.
You could regenerate the correct schema with a list of your coverage values in your JSON, but this needs to be a list
public Coverage1.Coverage[] values;
Therefore, change the getters and setters as well.
Then, you can cv.setValues(Coverage1.Coverage.values());
Or maybe, you tried to do this
List<Coverage1.Coverage> ae= new ArrayList<Coverage1.Coverage>(Arrays.asList( Coverage1.Coverage.values());
Or,
for(Coverage1.Coverage enumval: Coverage1.Coverage.values() ){
ae.add(enumval);
}
Basically, cv.setValue(enumval); can't be done in a loop because you'll overwrite the one value
I'd also suggest better names for the enum. And the one at the end of Coverage1 could be removed

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.

Deserializing child node with GSON

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");
}
}

Categories