Throughout my app, I request JSON data from my web server and the response is almost always in a different.
For example, one response might look like this:
{"success":true,"data":{"token_id":"pPt9AKl0Cg","token_key":"8ax224sFrJZZkStAQuER"}}
While another might look like this:
{"success":true,"data":{"user_id":"20","username":"Bob"}}
And another might look like this:
{"success":true,"data":{"user_id":"20","stats":{"followers":"500","following":"12"}}}
Previously, I created a model class (Java) for each different response type. For example, for the first response above, my model class might look like this:
public class MyResponseModel {
private boolean success;
private DataModel data;
public static class DataModel {
private String token_id;
private String token_key;
}
...
}
Is this really the best way of doing this? Because if I do this for the dozen+ responses I get across my app, I'll end up with a dozen+ different model classes, one for each different response.
Are there alternatives to parsing JSON?
Thanks.
You will need one DTO or model class for each type of response. The static typing is required to serialize/deserialize from/to json. You can use generics to wrap the response. Refactoring your code this will be something like:
public class MyResponseModel <T> {
private boolean success;
private T data;
}
public class DataModel {
private String token_id;
private String token_key;
}
Then your code can return MyResponseModel<DataModel> object for this scenario.
If you really want to use one class for every type of response you will need to represent all your response as key value pairs and then you can have one class containing a Map. I will not recommend that approach and would prefer to have one class for each type of response.
Check out https://github.com/jayway/JsonPath , it`s only in the Java world where the default solution is to serialize/deserialize.
Related
Let us consider that I have a file which looks like following:
#CreateFieldClass
public class Queue {
private String queueId;
private int order;
private boolean isActive;
/* Getters and Setters */
}
What I want is, If there is #CreateFieldClass annotation, I want to generat a new java file, in the same package which would look something like this
public class QueueFields {
public static final Field<Queue, String> QUEUE_ID = new Field<>(Queue.class, "queueId", DataType.STRING);
public static final Field<Queue, Integer> ORDER = new Field<>(Queue.class,"order", DataType.NUMBER);
public static final Field<Queue, Boolean> IS_ACTIVE = new Field<>(Queue.class,"isActive", DataType.Boolean);
}
I have a mapping of Java type to the "DataType" mentioned above.
I know ASM is one option to consider, but are there any better recommendations or even some ASM tutorials/examples someone can help me out.
To examine the annotated class, you can use reflection. Be aware that any fields that use generics will lose the generic parameter types due to erasure (if you need to get around that, then you need to parse the source code and work off of the parse tree). To generate the resulting class, you can do basic String concatenation. If you want a more structured method for generating code, I like the codemodel library.
Here is my POJO
public class AllParticipantsDTO {
private List<SubmissionParticipantDTO> hairStylists;
private List<SubmissionParticipantDTO> mds;
private List<SubmissionParticipantDTO> muas;
private List<SubmissionParticipantDTO> phs;
private List<SubmissionParticipantDTO> setDesigner;
private List<SubmissionParticipantDTO> wardrobeStylists;
Which contains arrays of:
public class SubmissionParticipantDTO {
private String firstName;
private String lastName;
private CountryDto country;
private String city;
private Boolean me;
#POST
#Path("init")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public Response initSubmission(final AllParticipantsDTO allParticipantsDTO) {
I don't get why i'm getting 415.
I've also tried to add jersey-media-json-jackson to pom, still same issue
A few things to check, in this order. You say you checked those things, so I really think it's probably the GET vs POST. But anyways, double-check these three yet again, just in case:
Make sure that you have already set the appropriate header, i.e. Content-
Type="application/json; charset=utf8"
Make sure that the JSON object can be properly deserialized, i.e.
pay attention to lower and upper casing and also pay attention
whether i.e. a field setDesigner really IS an (empty) array and you just
consider it as a regular object (I am emphasizing this due to your
naming practice of that particular array)
Make sure that your route/path AND request type (I see #POST there) is correct.
Although it could be that there's some misspelling or that your JSON object simply isn't valid because it lacks some obligatory fields, I guess you already double-checked it already, so if I had to make a wild guess, I think it's because you keep sending i.e. a GET request instead of a POST
Looks like the problem was in POJO itself.
The SubmissionParticipantDTO had extra parameter in few arrays, so jersey couldn't handle it.
I need to use a response from a rest service returning JSON. However, one of the fields in the json response is the empty string. So, basically this:
{"wut":
{
"foo":"fooval",
"": "srsly"
}
}
So, I need to somehow translate this into a java class, as below:
#JsonIgnoreProperties(ignoreUnknown=true)
public class wut
{
#JsonProperty
private String foo;
#JsonProperty
private String <empty string???>;
//etc...
}
As you might expect, I don't have enough control over the endpoint to be able to give the property a name. Is there a way to handle this?
I'm using RestTemplate from spring to make the call, if that matters at all.
I have a response object say ResponseObj.
public class ResponseObject {
private String one;
private String two;
private String three;
private String relationshipCd;
private List listOfObjects;
}
Coming from RMI. So this definition is untouchable ..
I want to create A pojo as a copy of this with only diff :
instead of listOfObjects --> listOfSpecificType;
i Know specificType using Runtime info.
Is there a reflection way of doing. All material I searched, wants to first create a POJOtype. Which I want to avoid.
Let me know if any more clarification is needed.
Thanks,
AM.
This is a curious situation: I have a bean like this that store some information and I need generics, because the field "data" can contain different types of data.
public class Request<T> {
private String name;
private Integer code;
private T data;
/* Getter and setters */
}
The fact is that "data" is not always used and sometimes it can be null. And if I want to avoid raw types I have to define a type anyway, like this:
Request<Object> req = ....
Is there a better way of doing that, where I can both 1) Avoid raw types 2) Have a generic data field in my request objects ???
If you don't mind the request type, use Request<?> in your declaration.
If the request is empty (meaning there is no type, which can be set as data), declare it as Request<Void>
You could always use the Void type, e.g.
Request<Void> req = ...
or a wildcard:
Request<?> req = ...
Maybe you should consider to change object hierarhy. If you dont use data in some cases, maybe you should have two objects:
class Request {
private String name;
private Integer code;
/* Getter and setters */
}
class DataRequest<T> extends Request {
private T data;
/* Getter and setters */
}
and use:
Request req1 = new Request();
Request req2 = new DataRequest<String>();
Maybe you should think in a different way: In your case a Request not always has associated data. Modelling this with null-values is a bad decision, because you have to check for this every time you want to use your data. At some point you want to handle Request without data in a different way then Request with data.
Maybe you should make your Request to an interface containing Methods like getName() and getCode() and create two concrete classes RequestWithData<T> and RequestWithoutData implementing this interface. Then you can check on creation of an RequestWithData<T>-instance, if a non-null data is provided. Furthermore, you can express in your method signature that you require a Request with data or without data. This leads to a more clean design and avoids your problem.
Use the new 'Optional' type in Java 8. It was made specifically for cases like these. If you cannot, for whatever reason, use Java 8 yet, the Google Guava library also implements that type. Check this example : https://gist.github.com/9833966