Retrofit parse JSON response from API when model is in "data" object - java

How can I parse this response without having to create a separate response class for each entity.
{
"data": {
"id": 100,
"first_name": "Michael",
"last_name": "Blankenship"
}
}
I would like to have a generic class that can reference the data object and then just specify what type of class that should be used to parse the response
Something like this:
#Get
Call<User> getUser();
#Get
Call<Status> getStatus();
Without having to have multiple response classes for each type
public class UserResponse {
User data;
}
public class User {
String first_name;
String last_name;
}
public class StatusResponse {
Status data;
}

Workaround for this would create a generic class something like this
public class BaseResponseWrapper <T> {
#SerializedName("data")
private T data;
public BaseResponseWrapper(){
super();
}
public T getData() {
return data;
}
}

Related

Define generic parameter type of an object after a request

Summary
I'm trying to define the generic type of params based on the Type property when the request arrives at the controller ?
If the Type is UPDATE, set the generic type of params to MovieParam, if the type CREATE, set it to CarParam.
Request Json
{
"values":[
{
"context":{
"type":"UPDATE",
"ids":[1,2,3,4,5],
"params":{
"code":1256,
"year":588987,
"name":"Suits Mike Harvey Specter",
"channel":"NetFlix"
}
}
},
{
context":{
"type":"CREATE",
"ids":[1,2,3,4,5],
"params":{
"brand": "Chevrolett",
"engine": 2.0,
"segments": "Autos",
"year": "2014",
"name": "Celta"
}
}
}
]
}
Mappings in Java with Spring
public class Request {
List<Value> values;
}
public class Value {
Context context;
}
public class Context<T> {
String type;
List<Long> ids;
T params;
}
public class MovieParam {
Long code;
Long year;
String name;
String channel;
}
public class CarParam {
String brand;
Long engine;
String segments;
String name;
Long year;
}
My Controller
#PostMapping
private ResponseEntity<?> publish(#RequestBody Request request) {}
When my controller receives the payload shown above, the params property is of type linkedhashmap because it doesn't know the type of that object. I would like to transform this type to the corresponding shown above.
I would like to think of something simpler and more direct, sometimes an interceptor, or some implementation of a strategy based on Type

Multiple DTOs manual initialize

in Microservice, we post multiple dtos data as string json.
Controller:
#RequestMapping(value="/json",method = RequestMethod.POST)
public String getjson(#RequestBody String json) {
///Service process
}
Post Json:
{
"dtos":{
"Dto1":{
"name":"Dto1 Name Field",
"filter":[
{"key":"f1","value":1},
{"key":"f2","value":10}
]
},
"Dto2":{
"city":"Newyork",
"filter":[
{"key":"f1","value":1},
{"key":"f2","value":10},
{"key":"f3","value":10}
]
}
},
"page":1
}
DTO:
public class Dto1{
private String name;
}
public class Dto2{
private String city;
}
Dto1 and Dto2 is java DTO object name.
how to convert string json to java objects?
You can create a new DTO that contains all attrs and receive in request:
public class Filter{
private String key;
private int value;
}
public class Dto1{
private String name;
private List<Filter> filter;
}
public class Dto2{
private String city;
private List<Filter> filter;
}
public class Dtos{
public Dto1 dto1;
public Dto2 dto2;
}
public class DtoToReceiveInRequest{
private Dtos dtos;
private int page;
}
Controller
#PostMapping
public String getjson(#RequestBody DtoToReceiveInRequest json) {
///Service process
}
You can use the ObjectMapper from the jackson library, like below.
String json = "";
ObjectMapper objectMapper = new ObjectMapper();
Dto1 dto = objectMapper.readValue(json, Dto1.class);
But in your particular example, you don't have to have two DTO classes. You can encapsulate values in one DTO and have the list of different instances of that DTO in a json format.
NB. The json string should be a representation of the preferred class you want to retrieve, eg Dto1.java.

How to get instagram followers list with Java?

i want to parse Json with this format:
{"data": {
"user": {
"edge_follow": {
"count": 2554, "page_info": {
"node": {
"id": "5719761315", "username": "disneyangell" ...
"node": {
"id": "2260368333", "username": "moosa_sedaghat",...
"node": {
"id": "3982701506", "username": "alidadashi512", ...
.
.
.
from this link ;
i got my pojos from www.jsonschema2pojo.org/
i tried GsonConverter and Jackson ObjectMapper also
the problem is parsed object's node list is empty or it's zero always.
how to solve this?
if i need to use CustomConverter write that for this case.
So to get the JSON you want you have to be logged in to instagiam. Otherwise you will get an empty "edges" object in the JSON returned from your get request. If you are logged in here is an example to do it with Gson:
The POJO (maybe you need to add getter methods for fields you are interested in):
public class FollowJson{
Data data;
String status;
public ArrayList<FollowNode> getFollowNodes(){
return data.getFollowNodes();
}
class Data{
User user;
public ArrayList<FollowNode> getFollowNodes(){
return user.getFollowNodes();
}
}
class User{
EdgeFollow edge_follow;
public ArrayList<FollowNode> getFollowNodes(){
return edge_follow.getFollowNodes();
}
}
class EdgeFollow{
Integer count;
ArrayList<OuterNode> edges;
HashMap<String, Object> page_info;
public ArrayList<FollowNode> getFollowNodes(){
ArrayList<FollowNode> bufList = new ArrayList<FollowNode>();
for(OuterNode outer : edges){
bufList.add(outer.getNode());
}
return bufList;
}
}
class OuterNode{
FollowNode node;
public FollowNode getNode(){
return node;
}
}
class FollowNode {
Boolean followed_by_viewer;
String full_name;
String id;
Boolean is_verified;
String profile_pic_url;
Boolean requested_by_viewer;
String username;
public Boolean getFollowedStatus(){
return followed_by_user;
}
public String getId(){
return id;
}
public String getUsername(){
return username;
}
}
}
Then pass the POJO.class and the JSON string to the Method:
public <T> T getJsonFromString(String jsonString, Class<T> var){
GsonBuilder builder = new GsonBuilder();
return builder.create().fromJson(jsonString, var);
}
You can then call getFollowNodes() on the returned object, which returns an array of objects (FollowNode) representing the "nodes" in the JSON.

REST with nested JSON

I have a JSON Object
{
"firstname": "foo",
"account":
{
"city": "bar"
}
}
which I want serialize in a REST backend:
#POST
public Response create(Employee e)
Classes:
public class Employee {
public String firstname;
private Address address;
}
public class Address {
public String city;
}
Unforutanetly, I always receive a 400 status code. But if I do
public Response create(Object o)
everything works fine. Any ideas?
Your JSON does not correspond (map) to your POJO types. In the JSON, you have account, but in your Java type you have address.

Not able to populate pojo with RestAPI Data

I am using android-bootsrap from this link for my project from
https://github.com/AndroidBootstrap/android-bootstrap
I retained the project structure as it is and not performing authentication. In my apps i am making a call to a rest API which is returning the data in Json format. Using retrofit we are calling the services and getting the data in Json also.
We have created one POJO class for Json API. But in my app we are unable to get the Pojo object populated with Rest API data.
My code look as follows:
User.java
public class User implements Serializable {
private String shortDescription;
private String name;
public String getShortDescription() { return shortDescription;}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
UserService.java
public interface UserService {
#GET("/search/items")
UsersWrapper getUsers();
}
UserWrapper.java
public class UsersWrapper {
private User results;
public User getResults() { return results; }
}
MainActivity.class
public class MainActivity extends BaseActivity {
String data = "";
private User user;
#Inject protected BootstrapServiceProvider serviceProvider;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyTask().execute();
}
// making async request
class MyTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
try {
user = serviceProvider.getService().getUsers();
user.getShortDescription(); // here i am getting NullPointerException
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
}
I am getting the data in the retrofit log but when i am trying to get data through User object i am getting NullPointerException.
My Json data is as follows:
{"name":"user1","short_description":"user1 is a postgraduate student"}
So, the way you have your User/UserWrapper class setup GSON is expecting a JSON result that looks like:
{
"results": {
"name": "user1",
"short_description": "user1 is a postgraduate student"
}
}
If the JSON Result is just the stuff inside of the "results" block in my above example you would want to ditch the UserWrapper all together, and change your Service Interface to look like:
public interface UserService {
#GET("/search/items")
User getUsers();
}
If the JSON Result is an Array of Users such as
[
{
"name": "user1",
"short_description": "user1 is a postgraduate student"
},
...
]
Then you would want your Interface to look like:
public interface UserService {
#GET("/search/items")
List<User> getUsers();
}

Categories