I have the following JSON data:
{
"response": {},
"errorMessage": {
"error": [
{
"errorId": 260003,
"domain": "ads",
"subdomain": "asd",
"severity": "asd",
"category": "asd",
"message": "asdsa asd ad",
"errorName": "UnAuthorized"
}
]
}
}
Currently I have the following class structure:
public class JSONCollection
private Response response;
private ErrorMessage error;
public class Response
private String collectionId;
private String url;
public class ErrorMessage
private List<ErrorValues> error;
public class ErrorValues
private String errorId;
private String domain;
private String subdomain;
private String severity;
private String category;
private String message;
private String errorName;
I have setters/get set for all private variables
But when I do a JSONCollection cJson = gson.fromJson(JSONValue,JSONCollection.class); I get cJson as a null.
How to get it right?
I used this tool shown by #JigarJoshi to generate my schema.
The only difference I found is I had to change the class name from ErrorValues to Error
Related
Currently, I am trying to return a costum created response from my REST API. My goal is to create the following response.
{
"status": "Success",
"message": "More details here",
"data": {
"records": [
{
"record": "Lorem ipsum",
"code": 0,
"errors": null
},
{
"record": "Lorem ipsum",
"code": 1,
"errors": [
"First error",
"Second error"
]
}
]
}
}
My API endpoint looks like the following.
#PostMapping(value="/my-url",
consumes=MediaType.APPLICATION_JSON_VALUE,
produces=MediaType.APPLICATION_JSON_VALUE)
public Response check_records(#RequestBody(required=true) Records records) {
// Do Stuff
}
The 'Response' class:
public class Response {
private String status;
private String message;
private Map<String, List<RecordResponse>> data;
// Default getter / setter
}
The 'RecordResponse' class:
public class RecordResponse {
private String record;
private Integer code;
private String[] errors;
The response itself is returning anything but JSON. Neither way it is returning an error or returns the object reference in the json:
{
"status": "Success",
"message": "More details here",
"data": {com.example.restservice.data#2071af5d}
}
You can use generics to have a decent typecontroll for your response wrapper
public class Response<T> {
private String status;
private String message;
private T data;
//all args contructor
}
and
public class Records{
List<RecordResponse> records;
}
public class RecordResponse {
private String record;
private Integer code;
private String[] errors;
public Response<Records> check_records(#RequestBody(required=true) Records records) {
RecordResponse recordResponses=//build responses
Records records=//build records
return new Response<Records>(status,message,records);
}
This should produce response close if not exact as you have requested
The Json file is:
{
"data": [
{
"name": "key",
"error": "key is not valid"
},
{
"name": "package_name",
"error": "package name is not valid"
}
],
"success": false,
"message": "information is not valid"
}
I've got a BaseModel which has "success","message", "data" and all of my responds are extended from this Class.
But "data is different for each response from the server.
I've made this so far:
public class BaseModel{
private Object data;
private boolean success;
private String message;
}
which data for this case of error will cast to an array of DataError:
public class DataError{
private String name;
private String error;
}
And i get an error which tells me :
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.mapp.Model.DataError
List<DataError> dataError = (List<DataError>)response.body().getData();
textView.append("Error:"+ dataError.get(0).getError());
You need to have a List<DataError> when parsing, Although it can also parse as a Map. Create data in BaseModel Generic this way you can reuse it other classes as well. naming it to BaseListModel cause it return a list.
public class BaseListModel<T>{
private List<T> data;
private boolean success;
private String message;
}
Now you can make the API call return BaseListModel<DataError> .
For parsing Object type responses you can create other base class .
public class BaseModel<T>{
private T data;
private boolean success;
private String message;
}
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;
I'm consuming a newsapi whose JSON response is similar to this;
{
"status": "ok",
"articles": [
{
"source": {
"id": "bbc-news",
"name": "BBC News"
},
"author": "BBC News",
"title": "Jubilation greets end of Mugabe era",
"description": "Zimbabweans celebrate late into the night after Robert Mugabe resigns, ending 37-year rule.",
"url": "http://www.bbc.co.uk/news/world-africa-42072673",
"urlToImage": "https://ichef.bbci.co.uk/images/ic/1024x576/p05nt3bn.jpg",
"publishedAt": "2017-11-22T02:46:09Z"
},
{
"source": {
"id": "bbc-news",
"name": "BBC News"
},
"author": "BBC News",
"title": "Dramatic moment N Korea soldier defects",
"description": "He raced across the border on foot, closely pursued by North Korean troops who shot at him several times.",
"url": "http://www.bbc.co.uk/news/world-asia-42075986",
"urlToImage": "https://ichef.bbci.co.uk/news/1024/cpsprodpb/F519/production/_98854726_p05ntph4.jpg",
"publishedAt": "2017-11-22T04:45:14Z"
},
{
....
}
]
}
I'm trying to consume that response using Retrofit 2 with GSON.
My POJO Classes are these;
NewsList.java
public class NewsList {
public Articles[] articles;
private String status;
#Override
public String toString() {
return "ClassPojo [articles = " + articles + ", status = " + status + "]";
}
// getters and setters
}
Articles.java
public class Articles {
private String publishedAt;
private String author;
private String urlToImage;
private String title;
private Source source;
private String description;
private String url;
// getters and setters
}
Source.java
public class Source {
private String id;
private String name;
// getters and setters
}
My Retrofit Client looks like this;
public interface NewsroomAPI {
String BASE_URL = "https://newsapi.org/v2/";
#GET("top-headlines")
Call<NewsList> loadNews(#Query("sources") String source);
}
In my MainActivity.java I make calls to the Retrofit client like this;
OkHttpClient okHttpClient = new OkHttpClient().newBuilder().addInterceptor(new Interceptor() {
#Override public okhttp3.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request.Builder builder = originalRequest.newBuilder().header("Authorization",
getString(R.string.newsroom_api_key));
Request newRequest = builder.build();
return chain.proceed(newRequest);
}
}).build();
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(NewsroomAPI.BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.client(okHttpClient).build();
NewsroomAPI getNewsAPI = retrofit.create(NewsroomAPI.class);
Call<NewsList> call = getNewsAPI.loadNews("bbc-news");
call.enqueue(new Callback<NewsList>() {
#Override public void onResponse(Call<NewsList> call, Response<NewsList> response) {
if (response.isSuccessful()) {
NewsList newslist = response.body();
Log.w(TAG, "Articles result: " + newslist);
} else {
Toast.makeText(getContext(), "Some error occurred while fetching results!",
Toast.LENGTH_SHORT).show();
}
}
#Override public void onFailure(Call<NewsList> call, Throwable t) {
Log.w(TAG, "Failed! ", t);
}
});
The problem comes when I run the activity and log the results.
I would expect a log with the status and the returned articles. However, the status is returned successfully, but the articles object is null. The output looks like this;
W/GlobalNewsFragment: Articles result: ClassPojo [articles = null, status = ok]
The problem seems to be coming from the way Retrofit2 is deserializing the returned JSON object. Is there anything I'm doing wrong?
These are the dependencies in my build.gradle file
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile "com.android.support:recyclerview-v7:26.1.0"
compile "com.squareup.okhttp3:okhttp:3.8.0"
Your POJO class should be like below.
public class Article {
#SerializedName("source")
#Expose
private Source source;
#SerializedName("author")
#Expose
private String author;
#SerializedName("title")
#Expose
private String title;
#SerializedName("description")
#Expose
private String description;
#SerializedName("url")
#Expose
private String url;
#SerializedName("urlToImage")
#Expose
private String urlToImage;
#SerializedName("publishedAt")
#Expose
private String publishedAt;
// your getter setter methods
}
Your NewsList POJO like below.
public class NewsList {
#SerializedName("status")
#Expose
private String status;
#SerializedName("articles")
#Expose
private List<Article> articles = null;
// getter setter
}
And your source POJO like below.
public class Source {
#SerializedName("id")
#Expose
private String id;
#SerializedName("name")
#Expose
private String name;
// getters setters
}
AFAIK Gson deserialize JsonArray into List. Try this:
public class NewsList {
public List<Articles> articles;
private String status;
//some code
}
Unable to map json string with java object, getting error JSON parse error: Can not construct instance of com.test.CPInput$Evc$Uni
error:
{
"timestamp": 1502270576300,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "**JSON parse error: Can not construct instance of com.test.CPInput$Evc$Uni: can only instantiate non-static inner class by using default, no-argument constructor; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.test.CPInput$Evc$Uni: can only instantiate non-static inner class by using default, no-argument constructor at [Source: java.io.PushbackInputStream#edc246; line: 20, column: 9] (through reference chain: com.test.CPInput["evc"]->com.test.CPInput$Evc["uni"]->java.util.ArrayList[0]**)",
"path": "/demo/addCustomer"
}
json
{
"customerId": "abcdef",
"customerSegment": {
"customerType": "customer type",
"customerSubtype": "subtype",
"industry": "industry",
"subIndustry": "subindustry",
"specialPopulation": " spl population"
},
"evc": {
"evcId": "evcid",
"action": "PR",
"serviceId": "assigned prod id",
"previousValues": {
"previousName":"evcId",
"previousValue":"EVC id - OLD"
},
"uni": [
{
"type": "uniA",
"uniId": "uni id",
"siteId": "sidt id",
"tspCode": "tsp code",
"elocId": "e loc id",
"siteClli": "site clli",
"uniAction": "PR",
"previousValues": {
"previousName":"evcId",
"previousValue":"EVC id - OLD"
}
},
{
"type": "uniZ",
"siteId": "sidt id",
"tspCode": "tsp code",
"elocId": "e loc id",
"siteClli": "site clli",
"uniAction": "PR",
"previousValues": {
"previousName":"evcId",
"previousValue":"EVC id - OLD"
}
}
]
},
"solutionType": "EPL",
"source": "Orion"
}
CPInput.java
public class CPInput {
private String customerId;
private CustomerSegment customerSegment;
private Evc evc;
private String solutionType;
private String source;
public CPInput() {
super();
}
public class CustomerSegment{
private String customerType;
private String customerSubtype;
private String industry;
private String subIndustry;
private String specialPopulation;
//getter setter
}
public class Evc{
private String evcId;
private String action;
private String serviceId;
private PreviousValues previousValues;
private List<CPInput.Evc.Uni> uni=new ArrayList<CPInput.Evc.Uni>();
//getter setter
public class PreviousValues{
private String previousName;
private String previousValue;
//getter setter
}
public class Uni{
private String type;
private String uniId;
private String siteId;
private String tspCode;
private String elocId;
private String siteClli;
private String uniAction;
private PreviousValues previousValues;
//getter setter
public class PreviousValues{
private String previousName;
private String previousValue;
//getter setter
}
//getter setter
}
DemoController.java
#RestController
#SpringBootApplication(scanBasePackages = {"com.test"})
#RequestMapping(value = "/demo")
public class DemoController {
#RequestMapping(method = RequestMethod.POST, value = "/addCustomer")
public CPOutput addCustomer(#RequestBody CPInput input) {
System.out.println(input);
return null;
}
}
Try to use static inner classes for: CustomerSegment, Evc, PreviousValues and Uni.
I always use static inner classes, and I don't have any problem like that.