Firestore can't convert Document toObject - java

Im trying to retrieve a Document but I just can't get it to work. Here is my Code:
fm.getColRefProgramms().document(programmKey).collection("items").document("HIXQobZtlMxn4OblgOMi").get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
String s = documentSnapshot.getId();
OverviewItem item = documentSnapshot.toObject(OverviewItem.class);
item.setKey(item.getKey());
}
});
String s return the correct Id, so the Document is found and loaded from the Database but it canĀ“t create a OverviewIdem Object from it.
I get this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[])' on a null object reference
And this is the OverviewItem Class:
public class OverviewItem implements IProgrammItem, Serializable{
private String instance;
private String key;
private Programm programm;
private ArrayList<BasicElement> elements;
public OverviewItem() {}
public void setInstance(String instance) {
this.instance = instance;
}
public String getInstance() {
return instance;
}
#Exclude
public Programm getProgramm() {
return programm;
}
#Exclude
public String getKey() {
return key;
}
#Exclude
public void setKey(String key) {
this.key = key;
}
#Exclude
public void setProgramm(Programm programm) {
this.programm = programm;
}
public ArrayList<BasicElement> getElements() {
return elements;
}
public void setElements(ArrayList<BasicElement> elements) {
this.elements = elements;
}
}
And this is my Document:

FIX: I waited for half an hour, then it started to retrieve the data (Date's value was retrieved and wasn't null anymore). Maybe the database takes time to update, so give it some time (if you added a new value or document) and then check again.
I'm facing the same issue. This is my code:
firebasefirestore.collection("events").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot documentSnapshots, #Nullable FirebaseFirestoreException e) {
for(DocumentChange doc: documentSnapshots.getDocumentChanges()){
if(doc.getType() == DocumentChange.Type.ADDED){
Map<String, Object> a = doc.getDocument().getData();
HomeViewModel event = doc.getDocument().toObject(HomeViewModel.class);
eventlist.add(event);
eventRecyclerAdapter.notifyDataSetChanged();
}
}
}
});
Here I created a variable 'a' to see the data, and the data is being successfully retrieved from Firestore (I was checking in the debugger).
Value of a
However when I use toObject(), Date is null.
My HomeViewModel class:
public class HomeViewModel{
private String Date;
private String Description;
private String Imagepath;
private String Title;
public void setDate(String date) {
this.Date = date;
}
public String getDate() {
return Date;
}
public String getImagepath() {
return Imagepath;
}
public void setImagepath(String imagepath) {
Imagepath = imagepath;
}
public void setDescription(String description) {
Description = description;
}
public void setTitle(String title) {
Title = title;
}
public String getDescription() {
return Description;
}
public String getTitle() {
return Title;
}
public HomeViewModel(){
}
public HomeViewModel(String title, String desc, String date, String imagepath) {
this.Title = title;
this.Description = desc;
this.Date = date;
this.Imagepath = imagepath;
}
}
Therefore it is clear that toObject is the problem.

Related

How to create Gson object for entity class which has timestamp value?

I have a payload string and want to change it to values of entity. The payload as below:
{"resultCode":"200","resultMessage":"Success","consent":[{"name":"A","sourceSystem":"IGN","updateBy":"Admin","remark":"good","version":"1.0","updateDate":1600658621871},{"name":"B","sourceSystem":"IGN","updateBy":"Admin","remark":"good","version":"2.0","updateDate":1874819158457},{"name":"C","sourceSystem":"IGN","updateBy":"Admin","remark":"good","version":"3.0","updateDate":1358819159457}]}
And the entities:
public class ListConsentResponse {
private String resultCode;
private String resultMessage;
private List<ConsentDTO> consent;
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public String getResultMessage() {
return resultMessage;
}
public void setResultMessage(String resultMessage) {
this.resultMessage = resultMessage;
}
public List<ConsentDTO> getConsent() {
return consent;
}
public void setConsent(List<ConsentDTO> consent) {
this.consent = consent;
}
}
public class ConsentDTO {
private String name;
private String sourceSystem;
private String updateBy;
private String remark;
private String version;
private Timestamp updateDate;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSourceSystem() {
return sourceSystem;
}
public void setSourceSystem(String sourceSystem) {
this.sourceSystem = sourceSystem;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public Timestamp getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Timestamp updateDate) {
this.updateDate = updateDate;
}
}
But when I parse to json using GsonBuilder :
ListConsentResponse listConsentResponse = Utility.createGsonObject()
.fromJson(payload, ListConsentResponse.class);
I have error:
com.google.gson.JsonSyntaxException: 1600658621871
Is there any way help me get parse the string with Timestamp value to entity. Or at least can I change the Timestamp value to String value in payload (For example change 1600658621871 to "1600658621871").
Thanks.

Firebase Firestore : Document is not mapping to Model class

I was trying to build an app using Firebase Firestore but after retrieving the data on SnapshotListener it is not mapping to my model.
Here is My Model class
public class BlogPost {
private String description;
private String image;
private String user_id;
private String thumbnail_url;
private Timestamp timestamp;
public BlogPost() {
}
public BlogPost(String description, String image, String user_id, String thumbnail_url, Timestamp timestamp) {
this.description = description;
this.image = image;
this.user_id = user_id;
this.thumbnail_url = thumbnail_url;
this.timestamp = timestamp;
}
public String getImageUrl() {
return image;
}
public void setImageUrl(String image) {
this.image = image;
}
public String getUserId() {
return user_id;
}
public void setUserId(String user_id) {
this.user_id = user_id;
}
public String getThumbnailUrl() {
return thumbnail_url;
}
public void setThumbnailUrl(String thumbnail_url) {
this.thumbnail_url = thumbnail_url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Timestamp getPostTime() {
return timestamp;
}
public void setPostTime(Timestamp timestamp) {
this.timestamp = timestamp;
}
}
To add data I am using this code:
firestore.collection("posts").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots, #Nullable FirebaseFirestoreException e) {
for (DocumentChange doc : queryDocumentSnapshots.getDocumentChanges()){
if (doc.getType() == DocumentChange.Type.ADDED){
BlogPost blogPost = doc.getDocument().toObject(BlogPost.class);
blogList.add(blogPost);`
blogRecyclerAdapter.notifyDataSetChanged();
}
}
}
});
Here is what I the object after mapping
BlogPost{description='post 6', image='null', user_id='null', thumbnail_url='null', timestamp=null}
Here is database structure screenshot
As you can see description mapped but all other fields are null.
Any help would be appreciated.
Two changes need to be done.
-> Make Every data member in your data class public
-> Annotate them with #PropertName()
public class BlogPost {
#PropertyName("description")
public String description;
#PropertyName("image")
public String image;
#PropertyName("user_id")
public String user_id;
#PropertyName("thumbnail_url")
public String thumbnail_url;
#PropertyName("timestamp")
public Timestamp timestamp;
}
try this.

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();

Model class for Firebase Database

Currently I have this model class to collect data from firebase database. To show the data I am using firebaserecycleradapter.
News.class
public class News {
private String message, author, thumb_author, type;
private Long timestamp;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getThumb_author() {
return thumb_author;
}
public void setThumb_author(String thumb_author) {
this.thumb_author = thumb_author;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
}
But the problem is there is another child named images that consist of pushId and an Object. This is how it looks
news {
message:"value"
author:"value"
thumb_author:"value"
type:"value"
timestamp:"value"
images {
pushId01:"value"
pushId02:"value"
pushId03:"value"
pushId04:"value"
pushId05:"value"
}
}
So my question is how can I add the image child to the news.class or is there any possible solution for this? My possible solution for this is to get the image child data inside the onBindViewHolder using databasereference.
Add a property to represent the images node. Since these are simple string key/value pairs, you can represent it with a Map<String,String>. So:
public class News {
private String message, author, thumb_author, type;
private Long timestamp;
public Map<String,String> images; // this is a new field for the images
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
...

How to extract array of json inside an attribute of type List from an object

I am using Flickr API to get the information of images and returns the following JSON:
{"photos":{"page":1,"pages":60,"perpage":100,"total":"5964","photo":[{"id":"21577339501","owner":"85277110#N02","secret":"31e850dfeb","server":"5785","farm":6,"title":"P1390956","ispublic":1,"isfriend":0,"isfamily":0}, {"id":"21577287101","owner":"85277110#N02","secret":"412990658f","server":"611","farm":1,"title":"P1400012","ispublic":1,"isfriend":0,"isfamily":0}]
I use this code in the Spring controller to deserialize the JSON:
Collection<Photos> readValues = objectMapper.readValue(new URL(url), new TypeReference<Collection<Photos>>() { });
And returns the following error:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
How can I solve this problem? I didn't found solutions.
Photos.class:
public class Photos {
#JsonProperty("page")
private Integer page;
#JsonProperty("pages")
private Integer pages;
#JsonProperty("perpage")
private Integer perpage;
#JsonProperty("total")
private Integer total;
#JsonProperty("photo")
#JsonDeserialize(contentAs = Photo.class, as = ArrayList.class)
private List<Photo> photo;
public Photos() {}
public Photos(Integer page, Integer pages, Integer perpage, Integer total,
List<Photo> photo) {
super();
this.page = page;
this.pages = pages;
this.perpage = perpage;
this.total = total;
this.photo = photo;
}
public Photos(List<Photo> photo) {
super();
this.photo = photo;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getPages() {
return pages;
}
public void setPages(Integer pages) {
this.pages = pages;
}
public Integer getPerpage() {
return perpage;
}
public void setPerpage(Integer perpage) {
this.perpage = perpage;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public List<Photo> getPhoto() {
return photo;
}
public void setPhoto(List<Photo> photo) {
this.photo = photo;
}
}
Photo.class:
public class Photo {
#JsonProperty("id")
private Integer id;
#JsonProperty("owner")
private String owner;
#JsonProperty("secret")
private String secret;
#JsonProperty("server")
private Integer server;
#JsonProperty("farm")
private Integer farm;
#JsonProperty("title")
private String title;
#JsonProperty("ispublic")
private Boolean isPublic;
#JsonProperty("isfriend")
private Boolean isFriend;
#JsonProperty("isfamily")
private Boolean isFamily;
public Photo() { }
public Photo(Integer id, String owner, String secret, Integer server,
Integer farm, String title, Boolean isPublic, Boolean isFriend,
Boolean isFamily) {
super();
this.id = id;
this.owner = owner;
this.secret = secret;
this.server = server;
this.farm = farm;
this.title = title;
this.isPublic = isPublic;
this.isFriend = isFriend;
this.isFamily = isFamily;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public Integer getServer() {
return server;
}
public void setServer(Integer server) {
this.server = server;
}
public Integer getFarm() {
return farm;
}
public void setFarm(Integer farm) {
this.farm = farm;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Boolean getIsPublic() {
return isPublic;
}
public void setIsPublic(Boolean isPublic) {
this.isPublic = isPublic;
}
public Boolean getIsFriend() {
return isFriend;
}
public void setIsFriend(Boolean isFriend) {
this.isFriend = isFriend;
}
public Boolean getIsFamily() {
return isFamily;
}
public void setIsFamily(Boolean isFamily) {
this.isFamily = isFamily;
}
}
The basic problem is that your json is not a Collection<Photos>, but a Map<String, Photos>, which has a single entry "photos" -> Photos instance.
I got your json to successfully deserialize by making the following changes...
A) Change the type being read:
Map<String, Photos> readValues = objectMapper.readValue(json, new TypeReference<Map<String, Photos>>() { });
Note that I read straight from a String (not a URL).
B) Change the type of Photo.id from Integer to Long, because your json has id values well exceeding max int size.
C) I added the missing two closing braces from your sample json to make it valid.
FYI, deserialization works with or without the #JsonDeserialize annotation on the List<Photo> photo field of Photos.
Here's some runnable code that works:
String json = "{\"photos\":{\"page\":1,\"pages\":60,\"perpage\":100,\"total\":\"5964\",\"photo\":[{\"id\":\"21577339501\",\"owner\":\"85277110#N02\",\"secret\":\"31e850dfeb\",\"server\":\"5785\",\"farm\":6,\"title\":\"P1390956\",\"ispublic\":1,\"isfriend\":0,\"isfamily\":0}, {\"id\":\"21577287101\",\"owner\":\"85277110#N02\",\"secret\":\"412990658f\",\"server\":\"611\",\"farm\":1,\"title\":\"P1400012\",\"ispublic\":1,\"isfriend\":0,\"isfamily\":0}]}}";
Map<String, Photos> readValues = new ObjectMapper().readValue(json, new TypeReference<Map<String, Photos>>() { });

Categories