parse complex Gson , nested inner class was not parsed - android

I use gson.fromJson(jsonStr, JVisitorResponse) method to parse the JSON reponse string, all were parsed except the inner class JUserUrls, there must be something wrong, my wrong usage of Gson caused this, please help me.
My outer reponse class defined below:
public class JVisitorResponse extends BaseResponsePojo {
public int count;
#SerializedName("visitor_list")
public ArrayList<JVisitor> visitorList;
public JVisitorResponse() {
}
}
JVIsitor class defined below:
public class JVisitor {
#SerializedName("user_id")
public long uid;
#SerializedName("user_name")
public String userName;
#SerializedName("user_urls")
public JUserUrls userHeadUrls;
}
JUserUrls class defiend below:
public class JUserUrls {
#SerializedName("main_url")
public String mainUrl;
}
my JSON response was
{
count:30,
visitor_list:[
{
user_id:333333,
user_name:"jason lee",
user_urls:{
main_url:"http://xxxxxxxxxx.jpg"
}
},
...
]
}

Related

GSON should ignore class attributes that do not appear in JSON

currently I'm playing with GSON and got into some trouble that I couldn't solve on my own.
I've got these three classes:
One abstract class CustomEntity
public abstract class CustomEntity {
private View customView;
public CustomEntity() {}
public void setCustomView(View customView) {
this.customView = customView;
}
public View getCustomView() {
return customView;
}
}
Another class LastChange which extends from CustomEntity
public class LastChange extends CustomEntity {
public Config config;
public LastChange() {}
#Override
public String toString() {
return "LastChange:" + config.toString();
}
public Config getConfig() {
return config;
}
public void setConfig(Config config) {
this.config = config;
}
}
And a third class Config
public class Config extends CustomEntity {
public String config;
public String nav_items;
public Config() {}
#Override
public String toString() {
return "config data:" + config + ", " + nav_items;
}
public String getConfig() {
return config;
}
public void setConfig(String config) {
this.config = config;
}
public String getNav_items() {
return nav_items;
}
public void setNav_items(String nav_items) {
this.nav_items = nav_items;
}
}
In the MainActivity I've tried to deserialize the following JSON into a LastChange object with GSON.
String lastChangeJson = "{\"config\":{\"config\":\"2016-07-20 15:32:14\",\"nav_items\":\"2016-08-24 12:36:06\"},\"background_images\":{\"background_url_landscape\":\"2015-07-28 17:21:56\",\"background_url\":\"2015-07-28 17:21:56\",\"icon_for_accessory_view\":\"2015-07-28 17:21:56\",\"icon_for_route_view\":\"2015-07-28 17:21:56\",\"background_url_landscape_big\":\"2015-07-28 17:21:56\",\"background_url_big\":\"2015-07-28 17:21:56\"},\"nav_content\":[{\"last_change\":\"2016-06-29 11:06:16\",\"pageId\":\"10262\"},{\"last_change\":\"2016-08-24 12:36:06\",\"pageId\":\"10264\"},{\"last_change\":\"2016-08-09 16:13:03\",\"pageId\":\"10378\"},{\"last_change\":\"2016-08-09 16:13:03\",\"pageId\":\"10263\"},{\"last_change\":\"2016-07-20 15:32:14\",\"pageId\":\"10265\"}]}";
CustomEntity lastChangeEntity = gson.fromJson(lastChangeJson, LastChange.class);
The code above gives me the following exception:
java.lang.SecurityException: Can't make method constructor accessible
at java.lang.reflect.Constructor.setAccessible(Constructor.java:336)
at com.google.gson.internal.ConstructorConstructor.newDefaultConstructor(ConstructorConstructor.java:101)
at com.google.gson.internal.ConstructorConstructor.get(ConstructorConstructor.java:83)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:99)
at com.google.gson.Gson.getAdapter(Gson.java:423)...
But if I remove the attribute "customView" from the class CustomEntity and its getter and setter, the deserialization works fine.
Anybody got an idea on how I can tell GSON to ignore class attributes, if they don't appear in my json?
Thanks in advance.
When building new gson instance:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Annotate every field you want to serialize with #Expose:
#Expose
public Config config;
Edit:
One small side note - try to avoid keeping references to views (or any Context-related objects) in your models. You may encounter memory leaks if you persist instances of this model in static way and it smells like mixing presentation and data layers, which is never good thing to do for code readability and maintainability.

Failed to handle RealmList<RealmList<RealmInt>> in Realm.io

My JSON data looks like this from server api
{
//...
PredecessorIds:[[1,2][3,4][5]]
//...
}
I can successfully handle the arrays of Integer or String by RealmList<RealmInt> but this time I failed with an error, because RealmList> is not supported saying, "Type parameter 'io.realm.realmList' is not within its bounds...."
For RealmInt see this link.
I tried to solve it using RealmList<RealmLista> where RealmLista extends from RealmObject and has a RealmList like this
public class RealmLista extends RealmObject {
public RealmList<RealmInt> value;
public RealmLista() {
}
public RealmLista(RealmList<RealmInt> val) {
this.value = val;
}
}
and then created a RealmListaTypeAdapter and added it to Gson but when deserializing Gson expects an Object (RealmLista) but is found array, as the data shown above from server is obvious.
//RealmListAdapter for Gson
#Override
public RealmLista read(JsonReader in) throws IOException {
RealmLista lista = new RealmLista();
Gson gson = new Gson();
//how to read that [[1],[3,4]] int into RealmLista
in.beginArray();
while (in.hasNext()) {
lista.value.add(new RealmInt(in.nextInt()));
}
in.endArray();
return lista;
}
Is there any way to store a simple List<List<Integer>> by converting to RealmObject of any type while saving, List<List<Integer>> is easily converted by Gson. :-/
Realm doesn't support lists of lists currently. See https://github.com/realm/realm-java/issues/2549.
So #EpicPandaForce's idea about creating a RealmObject that holds that inner list is probably the best work-around.
It could look something like this:
public class Top extends RealmObject {
private RealmList<ChildList> list;
}
public class ChildList extends RealmObject {
private RealmList<RealmInt> list;
}
public class RealmInt extends RealmObject {
private int i;
}
The correct link for the gist should be: https://gist.github.com/cmelchior/1a97377df0c49cd4fca9

Saving firebase ServerValue.TIMESTAMP on AutoValue POJOs

Android chat crashes on DataSnapshot.getValue() for timestamp
I'm trying to add a timestamp property to my POJO. The solution above tells jackson to ignore the real data member which is used by the application. I'm using AutoValue and can't figure out how I could annotate my class to get it to work.
#AutoValue
public abstract class Pojo {
#JsonProperty("id") public abstract String id();
#JsonProperty("name") public abstract String name();
#JsonProperty("date") public abstract long date();
#JsonCreator public static Pojo create(String id, String name, long date) {
return new AutoValue_Pojo(id, name, date);
}
}
I tried using a custom serializer:
public class TimeStampSerializer extends JsonSerializer<Long> {
#Override public void serialize(Long value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(ServerValue.TIMESTAMP.toString());
}
}
but that wrote the string date: "{.sv=timestamp}" to firebase instead of generating the timestamp
Caught my mistake:
#AutoValue
public abstract class Pojo {
#JsonProperty("id") public abstract String id();
#JsonProperty("name") public abstract String name();
//Custom serializer
#JsonSerialize(using = TimestampSerializer.class) #JsonProperty("date") public abstract long date();
#JsonCreator public static Pojo create(#JsonProperty("id") String id, #JsonProperty("name") String name, #JsonProperty("date") long date) {
return new AutoValue_Pojo(id, name, date);
}
}
public class TimestampSerializer extends JsonSerializer<Long> {
#Override public void serialize(Long value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
//Use writeObject() instead of writeString()
jgen.writeObject(ServerValue.TIMESTAMP);
}
}

Gson, parse object of arrays using retrofit

I have this server response:
{ "result" : true , "content" : {
"files" : [],
"filesNames" : [],
"folders" : []
}
}
How can i create a gson object to make retrofit adapt that response? Because this doesn't seem to work(i only need files and folders):
public class GetUserFilesAnswer {
public boolean result;
public List<Integer> files;
public List<String> folders;
}
client.getUserFiles(email, token, path, new Callback<GetUserFilesAnswer>() {
#Override
public void success(GetUserFilesAnswer getUserFilesAnswer, Response response) {
}
#Override
public void failure(RetrofitError error) {
}
});
Try this model:
public class GetUserFilesAnswer {
public static class Content {
public List<Integer> files;
public List<String> folders;
}
public boolean result;
public Content content;
}

Parse xml response using retrofit

i am unable to parse xml response using retrofit.
here is xml:
<ossi>
<eventdetail>
<maps>
<settings>...</settings>
<map>...</map>
<map>...</map>
</maps>
</eventdetail>
</ossi>
<------ EDIT ---------->
Here are models
#Root(name = "ossi")
public class RootEventDetail {
#Element
public EventDetail eventdetail;
}
public class EventDetail {
#Element
public General general;
#ElementList
public List<MenuItem> menu;
#ElementList
public List<WebViewItem> module_webview;
//TODO how can i create model for Maps ??????
#Element
public Maps maps;
}
public class Maps {
#Element
public MapSettings settings;
#Element
public List<EventMap> map;
}
How my model will look like?
Thanks in advance.
Finally i solved my problem. I used inline property to solve my issue.
Here is My Model:
public class Maps {
#ElementList(inline = true ,required = false)
public List<Map> map;
#Element
public Settings settings;
}
And Main class is:
public class EventDetail {
#Element
public Maps maps;
}

Categories

Resources