I am trying to make updates to my android app to accomodate the recent facebook changes with pictures. Previously i just got a string back for the user photo but not its returning an array. I have updated my code but the data is just coming back null, can someone point me in the right direction?
Thanks
GSON call
Gson gson = new GsonBuilder().create();
FBFriendResponse resp = gson.fromJson(response, FBFriendResponse.class);
New facebook data structure
"picture": {
"data": {
"url": "######.jpg",
"is_silhouette": false
}
}
public class FBFriend implements Comparable<FBFriend>
{
public String id, name, gender;
public FBFriendPicture picture;
#Override
public int compareTo(FBFriend another) {
return this.name.compareTo(another.name);
}
}
public class FBFriendPicture
{
public FBFriendPictureData pictureData;
}
public class FBFriendPictureData
{
public String friendPictureURL;
public Boolean friendPictureIssilhouette;
}
Resolved the issue. It was due to the wrong names used in the classes
public class FBFriend implements Comparable<FBFriend>
{
public String id, name, gender;
public FBFriendPicture picture;
#Override
public int compareTo(FBFriend another) {
return this.name.compareTo(another.name);
}
}
public class FBFriendPicture
{
public FBFriendPictureData data;
}
public class FBFriendPictureData
{
public String url;
public Boolean is_silhouette;
}
Related
I've found lots of answers on SO but none working for me.
I have a List<MyModel> myList that I want to pass and retrieve through Intents.MyModel implements Parcelable and its implementation.I am using intent.putExtra("my_key",(Parcelable) myList);At runtime it throws the exception
java.util.ArrayList cannot be cast to android.os.Parcelable
And if I use putParcelableArrayListExtra then it says wrong second argument type.Any explaination or other way would be helpfulEDIT: My Model class is :
public class Filter {
private String categoryId;
public List<PrimaryFilterData> getPrimaryFilterDataList() {
return primaryFilterDataList;
}
public void setPrimaryFilterDataList(List<PrimaryFilterData> primaryFilterDataList) {
this.primaryFilterDataList = primaryFilterDataList;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getCategoryId() {
return categoryId;
}
public void setCategoryId(String categoryId) {
this.categoryId = categoryId;
}
private String categoryName;
private List<PrimaryFilterData> primaryFilterDataList;
public static class PrimaryFilterData implements Parcelable
{
private String filterId;
protected PrimaryFilterData(Parcel in) {
filterId = in.readString();
filterName = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(filterId);
dest.writeString(filterName);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<PrimaryFilterData> CREATOR = new Creator<PrimaryFilterData>() {
#Override
public PrimaryFilterData createFromParcel(Parcel in) {
return new PrimaryFilterData(in);
}
#Override
public PrimaryFilterData[] newArray(int size) {
return new PrimaryFilterData[size];
}
};
public String getFilterName() {
return filterName;
}
public void setFilterName(String filterName) {
this.filterName = filterName;
}
public String getFilterId() {
return filterId;
}
public void setFilterId(String filterId) {
this.filterId = filterId;
}
public List<SecondaryFilterData> getSecondaryFilterDataList() {
return secondaryFilterDataList;
}
public void setSecondaryFilterDataList(List<SecondaryFilterData> secondaryFilterDataList) {
this.secondaryFilterDataList = secondaryFilterDataList;
}
private String filterName;
private List<SecondaryFilterData> secondaryFilterDataList;
}
public static class SecondaryFilterData implements Parcelable {
private String secFilterName;
private String secFilterId;
private boolean isChecked=false;
public SecondaryFilterData(){}
protected SecondaryFilterData(Parcel in) {
secFilterName = in.readString();
secFilterId = in.readString();
isChecked = in.readByte() != 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(secFilterName);
dest.writeString(secFilterId);
dest.writeByte((byte) (isChecked ? 1 : 0));
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<SecondaryFilterData> CREATOR = new Creator<SecondaryFilterData>() {
#Override
public SecondaryFilterData createFromParcel(Parcel in) {
return new SecondaryFilterData(in);
}
#Override
public SecondaryFilterData[] newArray(int size) {
return new SecondaryFilterData[size];
}
};
public boolean isChecked() {
return isChecked;
}
public void setIsChecked(boolean isChecked) {
this.isChecked = isChecked;
}
public String getSecFilterName() {
return secFilterName;
}
public void setSecFilterName(String secFilterName) {
this.secFilterName = secFilterName;
}
public String getSecFilterId() {
return secFilterId;
}
public void setSecFilterId(String secFilterId) {
this.secFilterId = secFilterId;
}
}
}
Now I wish to send list of Primary data from one activity to other
You can achieve this with a Bundle.
// Important - use array list not regular list.
// MyModel must implement Parcelable
ArrayList<MyModel> myList;
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("my_key", myList);
intent.putExtras(bundle);
If your list must be of type List you can convert it at the last minute.
bundle.putParcelableArrayList("my_key", new ArrayList<MyModel>(myList));
Then in the receiving activity.
List<MyModel> myList = getIntent().getParcelableArrayListExtra("my_key");
if your MyModel class contains data memeber of only primary or String type then
Implement java.io.Serializable interface in your MyModel class.
Use Intent.putExtra(String name, Serializable value) method to send the list of model with Intent.
Intent.getSerializableExtra(String name) to retrieve list back;
You can pass your java object as a Parcelable object in the bundle. But before that you need your model java class to implement Parcelable interface and override the necessary methods.
Once you have implemented the Parcelable interface you can easily pass your model class(java class) object as Parcelable to the bundle. Small snippet below:
yourBundle.putParcelable(YOUR_OBJ_KEY,yourModelObject);
Here, yourModelObject is the object of your model class that contains all the getters and setters method that you can use.
The point i am trying to make is that you pass your entire java object to the next activity rather than the list. By doing this you will get all the information that you require in your next activity inside this java object.
I think the problem is that your List does indeed not implement Parcelable. Its content does. Try to pass an array, not a List, of Parcelables:
intent.putExtra("my_key", myList.toArray());
Edit: I just saw that it is also possible to send lists but they have to be of type ArrayList. If you don't want to convert your List to an array, try to declare your List as ArrayList<MyModel> myList where MyModel must implement Parcelable.
Phew!
After long hours of work; I come to following conculsion (I'll update answer if I find some better reason).
Parceble/Serializablwe is passing value of list as reference; that's why when I was trying to access that list from other activity; it was returning null.
Currently ; I have maintained a global list(singleton using application class) and updating / retreiving it.
I am using Robospice + Retrofit + Jackson. I have not plain class which has another class object as a field. I need to parse json and create class with field.
Here is my class
#JsonIgnoreProperties(ignoreUnknown=true)
public class User implements UserInformationProvider {
#JsonProperty("customer_id")
public int id;
#JsonProperty("firstname")
public String firstName;
#JsonProperty("lastname")
public String lastName;
#JsonProperty("email")
public String email;
#JsonProperty("telephone")
public String phone;
#JsonProperty("token_api")
public String token;
#JsonProperty("token_expire")
public int tokenExpireTime;
public UserPreferences userPreferences;
#Override
public String getUserFirstName() {
return firstName;
}
#Override
public String getUserLastName() {
return lastName;
}
#Override
public String getUserEmail() {
return email;
}
#Override
public String getUserIconUrl() {
return null;
}
}
And preferences class
public class UserPreferences {
public boolean offersNotifications;
public boolean statusChangedNotifications;
public boolean subscriptionNotifications;
#JsonProperty("new_offers")
public boolean newOffersNotify;
#JsonProperty("order_status_changed")
public boolean orderStatusChangedNotify;
#JsonProperty("hot_offers")
public boolean hotOffersNotify;
}
Request that I need to parse into POJO.
{
"customer_id": 84,
"token_api": "ef5d7d2cd5dfa27a",
"token_expire_unix": "1435113663",
"preferences": {
"new_offers": "1",
"order_status_changed": "1",
"hot_offers": "1"
}
}
Please help, how can I do this using Jackson. I would be very grateful for any help. Thanks in advance.
The main problem lies inside of UserPreferences. Right now your code is attempting to deserialize "1" as a boolean. Java will not do this translation for you, so you will need to create a custom deserializer and apply it to the fields with numeric booleans.
Create a Custom Deserializer
A deserializer allows you to specify a class and apply custom operations to how it is created from JSON:
public class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {
#Override
public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
int intValue = p.getValueAsInt();
switch (intValue) {
case 0:
return Boolean.TRUE;
case 1:
return Boolean.FALSE;
default:
// throw exception or fail silently
}
return null; // can throw an exception if failure is desired
}
}
Apply Custom Deserialization to Fields
Since you probably don't want to register this on your ObjectMapper and apply it to all deserialization, you can use the #JsonDeserialize annotation. Your UserPreferences class will end up looking something like this:
public class UserPreferences {
public boolean offersNotifications;
public boolean statusChangedNotifications;
public boolean subscriptionNotifications;
#JsonProperty("new_offers")
#JsonDeserialize(using = NumericBooleanDeserializer.class)
public boolean newOffersNotify;
#JsonProperty("order_status_changed")
#JsonDeserialize(using = NumericBooleanDeserializer.class)
public boolean orderStatusChangedNotify;
#JsonProperty("hot_offers")
#JsonDeserialize(using = NumericBooleanDeserializer.class)
public boolean hotOffersNotify;
}
Make Sure #JsonProperty Matches JSON Keys
Since your JSON has "preferences" and the name of your Java property is userPreferences you will need to slap a #JsonProperty("preferences") on the property inside of User
I got json like below:
{"examinationTypes":[{"ExaminationTypeVO":{"id":1,"name":"Badanie krwi"}},{"ExaminationTypeVO":{"id":2,"name":"Spirometria"}},{"ExaminationTypeVO":{"id":3,"name":"Wymaz"}},{"ExaminationTypeVO":{"id":4,"name":"Ciśnienie"}},{"ExaminationTypeVO":{"id":5,"name":"EKG"}},{"ExaminationTypeVO":{"id":6,"name":"Elektrowstrząsy"}},{"ExaminationTypeVO":{"id":7,"name":"Tomografia"}},{"ExaminationTypeVO":{"id":8,"name":"Lewatywa"}},{"ExaminationTypeVO":{"id":9,"name":"Aneskopia"}},{"ExaminationTypeVO":{"id":10,"name":"Rektoskopia"}},{"ExaminationTypeVO":{"id":11,"name":"Kolonoskopioa"}},{"ExaminationTypeVO":{"id":12,"name":"Echo serca"}},{"ExaminationTypeVO":{"id":13,"name":"Ablacja"}},{"ExaminationTypeVO":{"id":14,"name":"Badnaie dopplerowskie"}},{"ExaminationTypeVO":{"id":15,"name":"Kapilaroskopia"}}]}
I have defined types:
#JsonRootName(value="ExaminationTypeVO")
#JsonIgnoreProperties(ignoreUnknown = true)
public class ExaminationTypeVO {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and
public class ExaminationTypesVO {
private List<ExaminationTypeVO> examinationTypes;
public List<ExaminationTypeVO> getExaminationTypes() {
return examinationTypes;
}
public void setExaminationTypes(List<ExaminationTypeVO> examinationTypes) {
this.examinationTypes = examinationTypes;
}
When I am deserializing it like that:
ExaminationTypesVO l = m.readValue(result, ExaminationTypesVO.class);
I receive an wrapper object but the list inside contains objects of type ExaminationTypeVO with all properties set to null.
Can anybody help to figure it out?
Your issue is that you have an extra level of object that you are trying to deserialize. Trying to not be confusing as I explain this: you have an array of objects, those objects contain a single ExaminationTypeVO object.
If you are stuck with the structure of the JSON that you provided, then you will need to add another "level" to your deserialization. You can do this via a wrapper object inside of your ExaminationTypesVO class:
public class ExaminationTypesVO {
private List<ExaminationTypeVOWrapper> examinationTypes;
public List<ExaminationTypeVOWrapper> getExaminationTypes() {
return examinationTypes;
}
public void setExaminationTypes(List<ExaminationTypeVOWrapper> examinationTypes) {
this.examinationTypes = examinationTypes;
}
public static class ExaminationTypeVOWrapper {
private final ExaminationTypeVO examinationTypeVO;
#JsonCreator
public ExaminationTypeVOWrapper(#JsonProperty("ExaminationTypeVO") ExaminationTypeVO examinationTypeVO) {
this.examinationTypeVO = examinationTypeVO;
}
public ExaminationTypeVO getExaminationTypeVO() {
return examinationTypeVO;
}
}
}
If you have control over the JSON that you are deserializing, you can just remove the extra "level" (ExaminationTypeVO wrapping object) and not have to change your code. Your new JSON in this approach would look like:
{
"examinationTypes": [
{
"id": 1,
"name": "Badanie krwi"
}, ...
]
}
With either of these approaches you can remove both of the class-level annotations you have on ExaminationTypeVO.
I am returning an array of results with my json Objects, and I am trying to use my customObjectResponse class to pull out each of the fields within each of the objects... the problem it is expecting an object so how do I edit my class to allow it to take in an array of object to be able to then call the fields of each object... I am confused as to what needs to be added:
Here is a response example of what is being passed to be used:
[
{
itemId: 'dfsdfsdf343434',
name: 'tests',
picture: '6976-7jv8h5.jpg',
description: 'testy.',
dateUpdated: 1395101819,
}
]
Here is my response Object Class:
public class ObjResponse{
private String itemId;
private String name;
private String picture;
private String description;
private String location;
private int dateUpdated;
private String msg;
//gridview constructor
public ObjResponse(String picture) {
this.picture = picture;
}
//public constructor
public ObjResponse() {
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getDateUpdated() {
return dateUpdated;
}
public void setDateUpdated(int dateUpdated) {
this.dateUpdated = dateUpdated;
}
public String getMsg() {
return msg;
}
}
what I am trying, but is not working, even if I separate the classes into their own files:
Data passed in:
items: [{obj1: "A", obj2: ["c", "d"]}, {etc...}]
public class Response {
public class List<Custom> {
private List<Custom> items;
}
public class Custom {
private String obj1;
private List<Obj2> obj2;
}
public Class Obj2 {
private String letters;
}
}
I ended up just calling in the callback a list of the customObject and it did the job...
new Callback<List<ObjResponse>>() {
I originally had trouble getting an idea of how the OP solved his problem but, after days of debugging I have finally figured out how to solve this issue.
So you essentially have data in the format like so (JSON Array of JSON Objects):
[
{
...
}
]
Your class that models the data and contains the getter and setter methods are nothing more than your typical POJO.
public class Person implements Serializable {
#SerializedName("Exact format of your json field name goes here")
private String firstName;
// Getters and Setters....
}
In your interface that contains your RESTful annotations you want to convert your call from:
Before:
public interface APInterface {
#GET("SOME URL TO YOUR JSON ARRAY")
Call<Person>(...)
}
After:
public interface APInterface {
#GET("SOME URL TO YOUR JSON ARRAY")
Call<List<Person>>(...)
}
In your android activity you want to convert all calls in the form of Call<Person> to Call<List<Person>>
Finally when making the initial asynchronous request call, you will want to convert your callbacks like so.
call.enqueue(new Callback<List<Person>>() {
#Override
public void onResponse(Call<List<Person>> call, Response<List<Person>> response) {
if(response.isSuccessful()){
List<Person> person = response.body();
// Can iterate through list and grab Getters from POJO
for(Person p: person){...}
} else {
// Error response...
}
}
#Override
public void onFailure(Call<List<Person>> call, Throwable t) {...}
});
Hope this helps others whom are lost from the accepted answer above.
This can also work by just passing an array of response objects. So if this is your response object:
public class CustomUserResponse {
public String firstName;
public String lastName;
...
}
You can use related syntax, depending on how you use the callbacks. Such as:
new Callback<CustomUserResponse[]>(){
#Override
public void success(CustomUserResponse[] customUserResponses, Response rawResponse) {
}
#Override
public void failure(RetrofitError error) {
}
};
OR
public class GetUserCommand implements Callback<CustomUserResponse[]> { ...
Put simply, in every place where you normally replace T with a response class, replace it with an array, instead as in CustomUserResponse[].
NOTE: to avoid confusing errors, be sure to also use an array in the Retrofit interface definition:
#POST ( "/users" )
public void listUsers(#Body GetUsersRequest request, Callback<CustomUserResponse[]> callback);
You could try something like this
JSONObject jsonObject = new JSONObject(<your JSON string result>);
JSONArray jsonArray = jsonObject.getJSONArray();
//use GSON to parse
if (jsonArray != null) {
Gson gson = new Gson();
ObjResponse[] objResponse = gson.fromJson(jsonArray.toString(), ObjResponse[].class);
List<ObjResponse> objResponseList = Arrays.asList(objResponse);
}
This should definitely work.
I am using Jackson to deserialize some xml. My xml has a value that can be an object or a string. Here is my xml
<FormFieldHidden name="RequestTime">
<DefaultValue>
<DataSourceName>DataSourceCurrentTime</DataSourceName>
</DefaultValue>
</FormFieldHidden>
<FormFieldHidden name="TradPtnrID">
<DefaultValue>043355932</DefaultValue>
</FormFieldHidden>
Here is my java:
#JsonIgnoreProperties(ignoreUnknown = true)
public class Forms {
public Form form;
public Forms() {
form = new Form();
}
public static class Form extends Asset {
public String version;
public String description;
public List<Section> sections;
}
public static class Section {
public String label;
public int totalColumns;
public List<FormFieldHidden> formFields;
}
public static class FormFieldHidden {
public String defaultValue;
}
}
How can I pull out the defaultValue whether it is an object or string?
I havent work with Jackson but maybe instanceof will help,
in pseudocode
if (value instanceof Class){Class c=value;}
else{String s=value;}