I\'m using retrofit with gson to deserialize my json into realm objects. This works very well for the most part. Trouble arises when dealing with
Rea
My gson typeAdapter was the culprit. The above error was seen as I wasnt deserializing the json into RealmPerson correctly, the first field is not a String, hence
in.nextString()
was borking.
I looked at some example code and it hit me, I didnt have to use
in.beginObject() and in.endObject()
to deserialize a String. The below code works.
public class QLRealmStringAdapter extends TypeAdapter<QLRealmString> {
@Override
public void write(JsonWriter out, QLRealmString value) throws IOException {
Log.e("DBG " + value.getValue(), "");
out.value(value.getValue());
}
@Override
public RealmString read(JsonReader in) throws IOException {
RealmString rString = new RealmString();
if (in.hasNext()) {
String nextStr = in.nextString();
System.out.println("DBG " + nextStr);
rString.setValue(nextStr);
}
return rString;
}
}
Hope this helps someone.
The error message "Expected a string but was NAME
" can be solved by retrieving the name of the json object in the JsonReader
before the actual json object (which is a String
in your case).
You can take a look at the Android documentation for JsonReader. It has detailed explanation and code snippet. You can also take a look at the readMessage
method in the sample code snippet in the documentation.
I have modified your read
method to what I think it should be. NOTE: I didn't test the code, so there may be some minor errors in it.
@Override
public RealmPerson read(JsonReader in) throws IOException {
RealmPerson rList = new RealmPerson();
in.beginObject();
String name = "";
while (in.hasNext()) {
name = in.nextName();
if (name.equals("userId")) {
String userId = in.nextString();
// update rList here
} else if (name.equals("otherStuff")) {
// since otherStuff is a RealmList of RealmStrings,
// your json data would be an array
// You would need to loop through the array to retrieve
// the json objects
in.beginArray();
while (in.hasNext()) {
// begin each object in the array
in.beginObject();
name = in.nextName();
// the RealmString object has just one property called "value"
// (according to the code snippet in your question)
if (name.equals("val")) {
String val = in.nextString();
// update rList here
} else {
in.skipValue();
}
in.endObject();
}
in.endArray();
} else {
in.skipValue();
}
}
in.endObject();
return rList;
}
Let me know if this helps.
It is better to use JsonSerializer and JsonDeserializer rather than TypeAdapter for your RealmObject
, because of 2 reasons:
They allow you to delegate (de)serialization for your RealmObject
to the default Gson (de)serializer, which means you don't need to write the boilerplate yourself.
There's a weird bug in Gson 2.3.1 that might cause a StackOverflowError
during deserialization (I tried the TypeAdapter
approach myself and encountered this bug).
Here's how (replace Tag
with your RealmObject
class):
(NOTE that context.serialize
and context.deserialize
below are equivalent to gson.toJson
and gson.fromJson
, which means we don't need to parse the Tag
class ourselves.)
Parser + serializer for RealmList<Tag>
:
public class TagRealmListConverter implements JsonSerializer<RealmList<Tag>>,
JsonDeserializer<RealmList<Tag>> {
@Override
public JsonElement serialize(RealmList<Tag> src, Type typeOfSrc,
JsonSerializationContext context) {
JsonArray ja = new JsonArray();
for (Tag tag : src) {
ja.add(context.serialize(tag));
}
return ja;
}
@Override
public RealmList<Tag> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
RealmList<Tag> tags = new RealmList<>();
JsonArray ja = json.getAsJsonArray();
for (JsonElement je : ja) {
tags.add((Tag) context.deserialize(je, Tag.class));
}
return tags;
}
}
Tag class:
@RealmClass
public class Tag extends RealmObject {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Then register your converter class with Gson:
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<RealmList<Tag>>() {}.getType(),
new TagRealmListConverter())
.create();
i need a jackson serializer and deserializer for the Converting Arraylist to RealmList