APICall response fails to parse data - java

I need to Parse data from this URL https://newsapi.org/v1/articles?apiKey=6946d0c07a1c4555a4186bfcade76398&sortBy=top&source=bbc-news , but when i make an apicall, it never enters onResponse function, but always onFailure.
Always getting an "ERROR" Toast that is in onFailure.
I have tried changing BASE_URL and Query to several different options but it doesn't help. Maybe it is a problem with my object, but I can't find the mistake.
*****UPDATE*****: I changed my Object like said in comments, but still getting onFailure function.
MainActivity.java
public class MainActivity extends AppCompatActivity implements
OnItemClickListener{
public static final String EXTRA_TITLE="Title";
public static final String EXTRA_DESCRIPTION="Description";
public static final String EXTRA_URL="URL";
private RecyclerView recycler;
private RecyclerAdapter adapter;
private ArrayList<NewsCell> newsList;
private Call<List<NewsCell>> apiCall;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
newsList=new ArrayList<>();
setupRecycler();
setUpApiCall();
}
private void setUpApiCall(){
apiCall=NetworkUtils.getApiInterface().getNews(
"6946d0c07a1c4555a4186bfcade76398","top","bbc-news");
apiCall.enqueue(new Callback<List<NewsCell>>() {
#Override
public void onResponse(Call<List<NewsCell>> call,
Response<List<NewsCell>> response) {
if(response.isSuccessful() && response.body().size()!=0){
newsList.addAll(response.body());
adapter=new
RecyclerAdapter(MainActivity.this,newsList,MainActivity.this);
recycler.setAdapter(adapter);
}
else{
Toast.makeText(MainActivity.this, "No results",
Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<List<NewsCell>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Error",
Toast.LENGTH_SHORT).show();
}
});
}
private void setupRecycler() {
recycler=findViewById(R.id.recyclerView);
recycler.setLayoutManager(new LinearLayoutManager(this));
}
#Override
public void onItemClick(int position) {
Intent detailIntent=new Intent(this,NewsSingle.class);
NewsCell clickedItem=newsList.get(position);
detailIntent.putExtra(EXTRA_TITLE,clickedItem.getTitle());
detailIntent.putExtra(EXTRA_DESCRIPTION,clickedItem.getDescription());
detailIntent.putExtra(EXTRA_URL,clickedItem.getUrlToImage());
startActivity(detailIntent);
}
}
NetvorkUtils.java
public class NetworkUtils {
private static final String BASE_API="https://newsapi.org/v1/";
private static APIInterface apiInterface;
public static APIInterface getApiInterface(){
if(apiInterface==null){
Retrofit retrofit =new Retrofit.Builder()
.baseUrl(BASE_API)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiInterface=retrofit.create(APIInterface.class);
}
return apiInterface;
}
}
APIInterface.java
public interface APIInterface {
#GET("articles")
Call<List<NewsCell>> getNews(#Query("apiKey") String key, #Query("sortBy")
String sort,#Query("source") String source);
}
Article.java
public class Article {
#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;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUrlToImage() {
return urlToImage;
}
public void setUrlToImage(String urlToImage) {
this.urlToImage = urlToImage;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
}
NewsCell.java
public class NewsCell {
#SerializedName("status")
#Expose
private String status;
#SerializedName("source")
#Expose
private String source;
#SerializedName("sortBy")
#Expose
private String sortBy;
#SerializedName("articles")
#Expose
private List<Article> articles = null;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getSortBy() {
return sortBy;
}
public void setSortBy(String sortBy) {
this.sortBy = sortBy;
}
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
}

You are getting response like this
but in your model class NewsCell you are parsing only title ,description and urlToImage .which is inside articles array
#SerializedName("title")
#Expose
private String title;
#SerializedName("description")
#Expose
private String description;
#SerializedName("urlToImage")
#Expose
private String urlToImage;
So I would suggest you to copy whole your response . goto this site and generate your model class properly . and paste in into your NewsCell

Related

How do I deserialize a JSON representation containing array of objects using jackson?

I have the exact same JSON representation as here: https://newsapi.org/docs/endpoints/top-headlines
To deserialize this into java objects I have created a News and a Article class. News contains multiple Articles. So here are my classes:
News:
public class News {
private String status;
private int totalResults;
private Article[] articles;
public News() {
}
public News(String status, int totalResults, Article[] articles) {
this.status = status;
this.totalResults = totalResults;
this.articles = articles;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public int getTotalResults() {
return totalResults;
}
public void setTotalResults(int totalResults) {
this.totalResults = totalResults;
}
public Article[] getArticles() {
return articles;
}
public void setArticles(Article[] articles) {
this.articles = articles;
}
}
Article:
public class Article {
private String source;
private String author;
private String title;
private String description;
private String url;
private String imageUrl;
private String publishedAt;
private String content;
public Article() {
}
public Article(String source, String author, String title, String description, String url, String imageUrl,
String publishedAt, String content) {
this.source = source;
this.author = author;
this.title = title;
this.description = description;
this.url = url;
this.imageUrl = imageUrl;
this.publishedAt = publishedAt;
this.content = content;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
Now I am using the com.fasterxml.jackson.databind.ObjectMapper as following to deserialize the JSON representation into a News object:
ObjectMapper objectMapper = new ObjectMapper();
News news = objectMapper.readValue(response.toString(), News.class);
Here I am getting a com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
The problem apparently is the array of articles representated in JSON.
I have read about arrays deserialization in jackson but I found nothing about deserialization of objects that contain properties AND array of objects. https://www.baeldung.com/jackson-deserialization
How do I do this properly using the ObjectMapper? Am I missing out on something? Any help is appreciated, thanks!
Your source mapping is wrong,
the source field is of format
source": {
"id": "google-news",
"name": "Google News"
}
this can be replaced with
public class Source {
private String id;
private String name;
public Source() {}
public Source(String id, String name) {
this.id = id;
this.name = name;
}
}
and replace
private String source;
with
private Source source;
in the Article class

Json error for Java with Gson and retrofit [Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 70 path $.Data]

I am consuming an API about cryptocurrency news called CryptoCompare.
My problem is that I can't detect what my code error is.
The error is as follows -> com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 70 path $.Data
I copy the Json and my two classes to help me find the solution.
Json:
{
"Type": 100,
"Message": "News list successfully returned",
"Promoted": [
],
"Data": [
{
"id": "2940487",
"guid": "https://cointelegraph.com/news/australian-hacker-pleads-guilty-to-stealing-450-000-in-xrp-last-year",
"published_on": 1566590880,
"imageurl": "https://images.cryptocompare.com/news/cointelegraph/dj0O90McM86.png",
"title": "Australian Hacker Pleads Guilty to Stealing $450,000 in XRP Last Year",
"url": "https://cointelegraph.com/news/australian-hacker-pleads-guilty-to-stealing-450-000-in-xrp-last-year",
"source": "cointelegraph",
"body": "An Australian woman has pleaded guilty to stealing $450,000 in XRP",
"tags": "Altcoin|Australia|Fraud|Hackers|XRP|Tokens|Police",
"categories": "XRP|ICO|Altcoin",
"upvotes": "0",
"downvotes": "0",
"lang": "EN",
"source_info": {
"name": "CoinTelegraph",
"lang": "EN",
"img": "https://images.cryptocompare.com/news/default/cointelegraph.png"
}
},
]
Link of Api -> https://min-api.cryptocompare.com/data/v2/news/?lang=EN
Java Class News:
public class News {
#SerializedName("Type")
#Expose
private Integer type;
#SerializedName("Message")
#Expose
private String message;
#SerializedName("Data")
#Expose
private List<Article> articles = null;
#SerializedName("HasWarning")
#Expose
private Boolean hasWarning;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
public Boolean getHasWarning() {
return hasWarning;
}
public void setHasWarning(Boolean hasWarning) {
this.hasWarning = hasWarning;
}
Java Class Article:
public class Article {
#SerializedName("id")
#Expose
private String id;
#SerializedName("guid")
#Expose
private String guid;
#SerializedName("published_on")
#Expose
private Integer publishedOn;
#SerializedName("imageurl")
#Expose
private String imageurl;
#SerializedName("title")
#Expose
private String title;
#SerializedName("url")
#Expose
private String url;
#SerializedName("source")
#Expose
private String source;
#SerializedName("body")
#Expose
private String body;
#SerializedName("tags")
#Expose
private String tags;
#SerializedName("categories")
#Expose
private String categories;
#SerializedName("upvotes")
#Expose
private String upvotes;
#SerializedName("downvotes")
#Expose
private String downvotes;
#SerializedName("lang")
#Expose
private String lang;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getGuid() {
return guid;
}
public void setGuid(String guid) {
this.guid = guid;
}
public Integer getPublishedOn() {
return publishedOn;
}
public void setPublishedOn(Integer publishedOn) {
this.publishedOn = publishedOn;
}
public String getImageurl() {
return imageurl;
}
public void setImageurl(String imageurl) {
this.imageurl = imageurl;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public String getCategories() {
return categories;
}
public void setCategories(String categories) {
this.categories = categories;
}
public String getUpvotes() {
return upvotes;
}
public void setUpvotes(String upvotes) {
this.upvotes = upvotes;
}
public String getDownvotes() {
return downvotes;
}
public void setDownvotes(String downvotes) {
this.downvotes = downvotes;
}
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}
Interface to call Api:
public interface ApiInterface {
#GET("news")
Call<News> getNews(
#Query("lang") String lang,
#Query("api_key") String apiKey,
#Query("lTs") int lTs
);
Retrofit Class Builder
public static Retrofit getApiClient(String BASE_URL){
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.client(getUnsafeOkHttpClient().build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
Fragment of Code when i call the api
private void LoadJson(){
swipeRefreshLayout.setRefreshing(true);
final ApiInterface apiInterface = ApiClient.getApiClient(ApiUtils.BASE_URL_NEWS).create(ApiInterface.class);
Call<News> call;
call = apiInterface.getNews("EN", ApiUtils.API_KEY,0);
call.enqueue(new Callback<News>() {
#Override
public void onResponse(Call<News> call, Response<News> response) {
if (response.isSuccessful() && response.body() != null){
articles.addAll(response.body().getArticles());
if (articles.size() - response.body().getArticles().size() == 0){
adapterNews.notifyDataSetChanged();
} else {
adapterNews.notifyItemRangeInserted(articles.size() - response.body().getArticles().size(), response.body().getArticles().size());
}
swipeRefreshLayout.setRefreshing(false);
progressBar.setVisibility(View.GONE);
} else {
Toast.makeText(getContext(), "No result", Toast.LENGTH_SHORT).show();
swipeRefreshLayout.setRefreshing(false);
progressBar.setVisibility(View.GONE);
}
}
#Override
public void onFailure(Call<News> call, Throwable t) {
Log.e(TAG, "ERROR API: " + t.getMessage() + " - " + t.getCause());
}
});
}
Any contribution is very helpful.
Thank you
FIXED THE PROBLEM WAS IN THE CALL
I notice that when you try query on api with wrong value like this
https://min-api.cryptocompare.com/data/v2/news/?lang=en
gives you json instead of array for data so this produce error
For fix and test instead of Locale.getDefault().getLanguage() use just "EN" and check the result
also for more help you can use this logging-interceptor

Why i'm getting expected begin_array but was String

This is my json data
{
"Success": true,
"Message": "User Not Found",
"Customer_Data": "",
"Customer_Device": "",
"Customer_Event": "",
"All_Event": [
{
"event_id": 6,
"event_name": "Test Event - 1",
"start_date": "01/06/2019",
"end_date": "01/06/2019",
"address_1": "Mumbai",
"address_2": "Mumbai",
"location_link": "https://goo.gl/maps/vTia6DQxwmiA5kvz6",
"pincode": 400060,
"state_id": 10,
"city_id": 355,
"sechudel": "Test",
"itinerary": "Test",
"edate": "2019-05-09T17:00:05.95592",
"eventimg": "http://zaidicorp.in/login/ProcessImage/636935218388448729.png"
}
],
"Status": 1,
"Currentdate": "5/16/2019 11:40:54 AM"
}
this is my pojo file
package mytraining.com.mytraining.Pojo;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
public class OtpCheck implements Serializable {
#SerializedName("Success")
#Expose
private Boolean success;
#SerializedName("Message")
#Expose
private String message;
#SerializedName("Customer_Data")
#Expose
private List<CustomerData> customerData;
#SerializedName("Customer_Device")
#Expose
private List<CustomerDevice> customerDevice;
#SerializedName("Customer_Event")
#Expose
private List<CustomerEvent> customerEvent;
#SerializedName("Event")
#Expose
private List<EventDetail> eventDetails;
#SerializedName("Status")
#Expose
private Integer status;
#SerializedName("Currentdate")
#Expose
private String currentdate;
public List<EventDetail> getEventDetails() {
return eventDetails;
}
public void setEventDetails(List<EventDetail> eventDetails) {
this.eventDetails = eventDetails;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<CustomerData> getCustomerData() {
return customerData;
}
public void setCustomerData(List<CustomerData> customerData) {
this.customerData = customerData;
}
public List<CustomerDevice> getCustomerDevice() {
return customerDevice;
}
public void setCustomerDevice(List<CustomerDevice> customerDevice) {
this.customerDevice = customerDevice;
}
public List<CustomerEvent> getCustomerEvent() {
return customerEvent;
}
public void setCustomerEvent(List<CustomerEvent> customerEvent) {
this.customerEvent = customerEvent;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getCurrentdate() {
return currentdate;
}
public void setCurrentdate(String currentdate) {
this.currentdate = currentdate;
}
/**
* Inner Class For Customer Data
*/
public static class CustomerData implements Serializable {
#SerializedName("cust_id")
#Expose
private Integer custId;
#SerializedName("cust_email")
#Expose
private String custEmail;
#SerializedName("customername")
#Expose
private String customername;
#SerializedName("personalcontact")
#Expose
private String personalcontact;
public Integer getCustId() {
return custId;
}
public void setCustId(Integer custId) {
this.custId = custId;
}
public String getCustEmail() {
return custEmail;
}
public void setCustEmail(String custEmail) {
this.custEmail = custEmail;
}
public String getCustomername() {
return customername;
}
public void setCustomername(String customername) {
this.customername = customername;
}
public String getPersonalcontact() {
return personalcontact;
}
public void setPersonalcontact(String personalcontact) {
this.personalcontact = personalcontact;
}
}
/**
* Inner Class For Customer Device
*/
public static class CustomerDevice implements Serializable {
#SerializedName("cust_id")
#Expose
private Integer custId;
#SerializedName("Cust_device")
#Expose
private String custDevice;
#SerializedName("bg_device_Brand")
#Expose
private String bgDeviceBrand;
#SerializedName("bg_device_model")
#Expose
private String bgDeviceModel;
#SerializedName("android_ver")
#Expose
private String androidVer;
#SerializedName("device_mac")
#Expose
private String deviceMac;
#SerializedName("opt")
#Expose
private Object opt;
public Integer getCustId() {
return custId;
}
public void setCustId(Integer custId) {
this.custId = custId;
}
public String getCustDevice() {
return custDevice;
}
public void setCustDevice(String custDevice) {
this.custDevice = custDevice;
}
public String getBgDeviceBrand() {
return bgDeviceBrand;
}
public void setBgDeviceBrand(String bgDeviceBrand) {
this.bgDeviceBrand = bgDeviceBrand;
}
public String getBgDeviceModel() {
return bgDeviceModel;
}
public void setBgDeviceModel(String bgDeviceModel) {
this.bgDeviceModel = bgDeviceModel;
}
public String getAndroidVer() {
return androidVer;
}
public void setAndroidVer(String androidVer) {
this.androidVer = androidVer;
}
public String getDeviceMac() {
return deviceMac;
}
public void setDeviceMac(String deviceMac) {
this.deviceMac = deviceMac;
}
public Object getOpt() {
return opt;
}
public void setOpt(Object opt) {
this.opt = opt;
}
}
/**
* Inner Class For Customer Event
*/
public static class CustomerEvent implements Serializable {
#SerializedName("ticket_no")
#Expose
private String ticketNo;
#SerializedName("seat_no")
#Expose
private String seatNo;
#SerializedName("event_name")
#Expose
private String eventName;
#SerializedName("start_date")
#Expose
private String startDate;
#SerializedName("end_date")
#Expose
private String endDate;
#SerializedName("location_link")
#Expose
private String locationLink;
#SerializedName("edate")
#Expose
private String edate;
public String getTicketNo() {
return ticketNo;
}
public void setTicketNo(String ticketNo) {
this.ticketNo = ticketNo;
}
public String getSeatNo() {
return seatNo;
}
public void setSeatNo(String seatNo) {
this.seatNo = seatNo;
}
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public String getLocationLink() {
return locationLink;
}
public void setLocationLink(String locationLink) {
this.locationLink = locationLink;
}
public String getEdate() {
return edate;
}
public void setEdate(String edate) {
this.edate = edate;
}
}
/**
* Inner Class For Event Detail
*/
public static class EventDetail implements Serializable {
#SerializedName("event_id")
#Expose
private Integer eventId;
#SerializedName("event_name")
#Expose
private String eventName;
#SerializedName("start_date")
#Expose
private String startDate;
#SerializedName("end_date")
#Expose
private String endDate;
#SerializedName("address_1")
#Expose
private String address1;
#SerializedName("address_2")
#Expose
private String address2;
#SerializedName("location_link")
#Expose
private String locationLink;
#SerializedName("pincode")
#Expose
private Integer pincode;
#SerializedName("state_id")
#Expose
private Integer stateId;
#SerializedName("city_id")
#Expose
private Integer cityId;
#SerializedName("sechudel")
#Expose
private String sechudel;
#SerializedName("itinerary")
#Expose
private String itinerary;
#SerializedName("edate")
#Expose
private String edate;
#SerializedName("eventimg")
#Expose
private String eventimg;
public Integer getEventId() {
return eventId;
}
public void setEventId(Integer eventId) {
this.eventId = eventId;
}
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public String getAddress1() {
return address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getLocationLink() {
return locationLink;
}
public void setLocationLink(String locationLink) {
this.locationLink = locationLink;
}
public Integer getPincode() {
return pincode;
}
public void setPincode(Integer pincode) {
this.pincode = pincode;
}
public Integer getStateId() {
return stateId;
}
public void setStateId(Integer stateId) {
this.stateId = stateId;
}
public Integer getCityId() {
return cityId;
}
public void setCityId(Integer cityId) {
this.cityId = cityId;
}
public String getSechudel() {
return sechudel;
}
public void setSechudel(String sechudel) {
this.sechudel = sechudel;
}
public String getItinerary() {
return itinerary;
}
public void setItinerary(String itinerary) {
this.itinerary = itinerary;
}
public String getEdate() {
return edate;
}
public void setEdate(String edate) {
this.edate = edate;
}
public String getEventimg() {
return eventimg;
}
public void setEventimg(String eventimg) {
this.eventimg = eventimg;
}
}
}
this my is java calling class
private void eventDetial(Map<String, String> map) {
Call<OtpCheck> call = apiInterface.eventShow(map);
call.enqueue(new Callback<OtpCheck>() {
#Override
public void onResponse(Call<OtpCheck> call, Response<OtpCheck> response) {
List<OtpCheck.EventDetail> data = response.body().getEventDetails();
for (int i = 0; i < 1; i++) {
image = data.get(i).getEventimg();
Log.i("Data", "data");
Glide.with(getActivity()).load(image).into(imageView);
}
}
#Override
public void onFailure(Call<OtpCheck> call, Throwable t) {
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
I tried multiple ways from StackOverflow but still not getting error
expected begin_array but was String
Firstly got Error from below field, this 3 field is String but you set ArrayList. But it will be String. Like below.
"Customer_Data": "",
"Customer_Device": "",
"Customer_Event": "",
#SerializedName("Customer_Data")
#Expose
private String customerData;
#SerializedName("Customer_Device")
#Expose
private String customerDevice;
#SerializedName("Customer_Event")
#Expose
private String customerEvent;
Also, Have no any event field. so need change from
#SerializedName("Event")
#Expose
private List<EventDetail> eventDetails;
To
#SerializedName("All_Event")
#Expose
private List<EventDetail> eventDetails;
Your problem is in your #SerializedName:
#SerializedName("Event")
#Expose
private List<EventDetail> eventDetails;
The tag SerializedName must have the name of the element of the json. Then you must changue it for:
#SerializedName("All_Event")
#Expose
private List<EventDetail> eventDetails;

error in get response from api using retrofit to fetch it in recycleview

I'm trying to network with this api:
https://api.jikan.moe/v3/schedule
so I use retrofit by create ApiClient.java class and this is the code of it:
public class ApiClient {
public static final String BASE_URL = "http://api.themoviedb.org/3/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
and the interface for complete endpoint of link is like this:
public interface ApiInterface {
#GET("schedule")
Call<MainResponse> getSchedule();
}
so I used serializable in modeling data and I create the MainResponse.java class to get the main monday array in api:
public class MainResponse {
#SerializedName("monday")
private List<Schedule> monday;
public List<Schedule> getMonday() {
return monday;
}
public void setMonday(List<Schedule> monday) {
this.monday = monday;
}
}
then I create a new modeling class to get the list of object items of monday array in class Schedule.java:
public class Schedule {
#SerializedName("title")
private String title;
public Schedule(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
finally in MainActivity I call this:
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.schedule_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ApiInterface apiService =
ApiClient.getClient().create(ApiInterface.class);
Call<MainResponse> call = apiService.getSchedule();
call.enqueue(new Callback<MainResponse>() {
#Override
public void onResponse(Call<MainResponse> call, Response<MainResponse> response) {
int statusCode = response.code();
List<Schedule> schedule = response.body().getMonday();
recyclerView.setAdapter(new MainAdapter(schedule, R.layout.list_item_schedule, getApplicationContext()));
}
#Override
public void onFailure(Call<MainResponse> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
as you can see I used an recycleview to fetch the titles of monday array but the problem is when I run the app it's just crushed because of this:
Attempt to invoke virtual method 'java.util.List
com.example.user_pc.capstonestage2.MainResponse.getMonday()' on a null
object reference
and this is the whole dialog of error:
10-14 20:53:45.462 1050-1050/com.example.user_pc.capstonestage2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.user_pc.capstonestage2, PID: 1050
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.example.user_pc.capstonestage2.MainResponse.getMonday()' on a null object reference
atcom.example.user_pc.capstonestage2.MainActivity$1.onResponse(MainActivity.java:36)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
I can't understand why it's null
I found this error too in the logcat:
10-14 21:02:12.373 9046-9046/com.example.user_pc.capstonestage2
E/RecyclerView: No adapter attached; skipping layout
so if you need the code of adapter this is it:
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.MovieViewHolder> {
private List<Schedule> schedule;
private int rowLayout;
private Context context;
public static class MovieViewHolder extends RecyclerView.ViewHolder {
LinearLayout schedulesLayout;
TextView title;
public MovieViewHolder(View v) {
super(v);
schedulesLayout = (LinearLayout) v.findViewById(R.id.schedule_layout);
title = (TextView) v.findViewById(R.id.title);
}
}
public MainAdapter(List<Schedule> schedule, int rowLayout, Context context) {
this.schedule = schedule;
this.rowLayout = rowLayout;
this.context = context;
}
#Override
public MainAdapter.MovieViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
return new MovieViewHolder(view);
}
#Override
public void onBindViewHolder(MovieViewHolder holder, final int position) {
holder.title.setText(schedule.get(position).getTitle());
}
#Override
public int getItemCount() {
return schedule.size();
}
}
You have declared wrong the API URL is :
public static final String BASE_URL = "https://api.jikan.moe/v3/";
Your MainResponse should be like this :
public class MainResponse {
#SerializedName("request_hash")
#Expose
private String requestHash;
#SerializedName("request_cached")
#Expose
private Boolean requestCached;
#SerializedName("request_cache_expiry")
#Expose
private Integer requestCacheExpiry;
#SerializedName("monday")
#Expose
private List<Monday> monday = null;
public String getRequestHash() {
return requestHash;
}
public void setRequestHash(String requestHash) {
this.requestHash = requestHash;
}
public Boolean getRequestCached() {
return requestCached;
}
public void setRequestCached(Boolean requestCached) {
this.requestCached = requestCached;
}
public Integer getRequestCacheExpiry() {
return requestCacheExpiry;
}
public void setRequestCacheExpiry(Integer requestCacheExpiry) {
this.requestCacheExpiry = requestCacheExpiry;
}
public List<Monday> getMonday() {
return monday;
}
public void setMonday(List<Monday> monday) {
this.monday = monday;
}
}
The Genre class
public class Genre {
#SerializedName("mal_id")
#Expose
private Integer malId;
#SerializedName("type")
#Expose
private String type;
#SerializedName("name")
#Expose
private String name;
#SerializedName("url")
#Expose
private String url;
public Integer getMalId() {
return malId;
}
public void setMalId(Integer malId) {
this.malId = malId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
And finally the Monday class
public class Monday {
#SerializedName("mal_id")
#Expose
private Integer malId;
#SerializedName("url")
#Expose
private String url;
#SerializedName("title")
#Expose
private String title;
#SerializedName("image_url")
#Expose
private String imageUrl;
#SerializedName("synopsis")
#Expose
private String synopsis;
#SerializedName("type")
#Expose
private String type;
#SerializedName("airing_start")
#Expose
private String airingStart;
#SerializedName("episodes")
#Expose
private Integer episodes;
#SerializedName("members")
#Expose
private Integer members;
#SerializedName("genres")
#Expose
private List<Genre> genres = null;
#SerializedName("source")
#Expose
private String source;
#SerializedName("producers")
#Expose
private List<Object> producers = null;
#SerializedName("score")
#Expose
private Object score;
#SerializedName("licensors")
#Expose
private List<Object> licensors = null;
#SerializedName("r18")
#Expose
private Boolean r18;
#SerializedName("kids")
#Expose
private Boolean kids;
public Integer getMalId() {
return malId;
}
public void setMalId(Integer malId) {
this.malId = malId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getSynopsis() {
return synopsis;
}
public void setSynopsis(String synopsis) {
this.synopsis = synopsis;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getAiringStart() {
return airingStart;
}
public void setAiringStart(String airingStart) {
this.airingStart = airingStart;
}
public Integer getEpisodes() {
return episodes;
}
public void setEpisodes(Integer episodes) {
this.episodes = episodes;
}
public Integer getMembers() {
return members;
}
public void setMembers(Integer members) {
this.members = members;
}
public List<Genre> getGenres() {
return genres;
}
public void setGenres(List<Genre> genres) {
this.genres = genres;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public List<Object> getProducers() {
return producers;
}
public void setProducers(List<Object> producers) {
this.producers = producers;
}
public Object getScore() {
return score;
}
public void setScore(Object score) {
this.score = score;
}
public List<Object> getLicensors() {
return licensors;
}
public void setLicensors(List<Object> licensors) {
this.licensors = licensors;
}
public Boolean getR18() {
return r18;
}
public void setR18(Boolean r18) {
this.r18 = r18;
}
public Boolean getKids() {
return kids;
}
public void setKids(Boolean kids) {
this.kids = kids;
}
}
Your api link is https://api.jikan.moe/v3/schedule
but in your code you wrote
public static final String BASE_URL = "http://api.themoviedb.org/3/";
You can either change the base url to https://api.jikan.moe/v3/, or
provide the full url on GET annotation of getSchedule()
#GET("https://api.jikan.moe/v3/schedule")
Call<MainResponse> getSchedule();

retrofit 2.3.0 how to handle nested json?

I am kinda of new to retrofit and i am not sure how to handle a nested json structure like this. if any one can help how to parse this type of structure . i would really i appreciate it . i have been stuck for days
{
"status": "ok",
"totalResults": 20,
"articles": [
{
"source": {
"id": null,
"name": "Bradenton.com"
},
"author": "By EILEEN NG Associated Press",
"title": "Malaysia says search for missing plane to end in June",
"description": "An official says the search for Malaysia Airlines Flight 370 by a U.S. company will likely end in June, as families of passengers marked the fourth anniversary of the plane's disappearance with hope that the world's biggest aviation mystery will be solved.",
"url": "http://www.bradenton.com/news/business/article203286984.html",
"urlToImage": "http://www.mcclatchy-wires.com/incoming/ukogzw/picture203286949/alternates/LANDSCAPE_1140/Malaysia_Missing_Plane_57970.jpg",
"publishedAt": "2018-03-03T09:42:00Z"
}
]
}
the http://www.jsonschema2pojo.org/ to convert your json to POJO and use that for retrofit 2.3
If you don't know how many classes you need to make ,just copy and paste your json here click here.
This will help you and make your work easy.
Create some pojos:
class Source {
String id;
String name;
}
class Article{
Source source;
String author;
String title;
String description;
String url;
String urlToImage;
String publishedAt;
}
class GetArticlesResponse{
String status;
int totalResults;
List<Article> articles;
}
And then pass GetArticlesResponse to your retrofit call.
import retrofit2.Response;
import retrofit2.Call;
public interface YourInterface {
#GET("your_end_point")
Call<Response<GetArticlesResponse>> getArticles();
}
or if you're using RX:
import retrofit2.Response;
import rx.Observable;
public interface YourInterface {
#GET("your_end_point")
Observable<Response<GetArticlesResponse>> getArticles();
}
MainClass.java
public class MainClass {
#SerializedName("status")
#Expose
private String status;
#SerializedName("totalResults")
#Expose
private Integer totalResults;
#SerializedName("articles")
#Expose
private List<Article> articles = null;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Integer getTotalResults() {
return totalResults;
}
public void setTotalResults(Integer totalResults) {
this.totalResults = totalResults;
}
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
}
Article.java
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;
public Source getSource() {
return source;
}
public void setSource(Source source) {
this.source = source;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUrlToImage() {
return urlToImage;
}
public void setUrlToImage(String urlToImage) {
this.urlToImage = urlToImage;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
}
Source.java
public class Source {
#SerializedName("id")
#Expose
private Object id;
#SerializedName("name")
#Expose
private String name;
public Object getId() {
return id;
}
public void setId(Object id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Retrofit Interface
public interface YourInterface {
#GET("whatever api u are using")
Call<MainClass> getData(#Query("whatever key") String/int(whatever name)) //or leave blank
}
well when working with retrofit i suggest using Gson library with it which parses your json to an object type you should have created so first you should create an object representing your object from the response you get so it will be something like this in your case
public class Article implements Serializable {
private String author;
private String title;
private String description;
private String url;
private String urlToImage;
private String publishedAt;
private Source source;
public Story() {
}
public Story(String author,
String title,
Source source,
String description,
String url,
String urlToImage,
String publishedAt) {
this.author = author;
this.title = title;
this.source = source;
this.url = url;
this.urlToImage = urlToImage;
this.publishedAt = publishedAt;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUrlToImage() {
return urlToImage;
}
public void setUrlToImage(String urlToImage) {
this.urlToImage = urlToImage;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
public Source getSource() {
return source;
}
public void setSource(Source source) {
this.source = source;
}
}
and similarly create your other class which is the Source class containing your Source object
public class Source implements Serializable {
private id id;
private String name;
public Source() {
}
public Source(int id,
String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
now in your retrofit api code you could do something like this
#GET("YOUR_ENDPOINT/")
Call<JsonObject> getArticles(... put your required fields here example ...#Query("token") String token);
and in your activity do something like this
List mArticleList = new ArrayList<>();
String mTotalResults = "";
UserApi service = ServiceGenerator.createService(UserApi.class);
Call<JsonObject> result = service.getArticles(token);
result.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.code() == 200) {
mArticleList = null;
JsonArray data = response.body().getAsJsonObject("data").getAsJsonArray("articles");
mArticleList = new Gson().fromJson(data.toString(), new TypeToken<List<Article>>(){}.getType());
mTotalResults = response.body().getAsJsonObject("data").getAsString("totalResults");
//if you want it as an integer you could do something like
int totalResults = Integer.parseInt(mTotalResults);
//... do what you want with your list
//...
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
//do what you have to do in case of error
}
});
}
hope this helps

Categories