问题
Due to Realm inability to work with promotive types, which include String
s, I'm trying to implement a JsonDeserializer
just like in this question.
The issue is that I'm baffled on to why I'm getting the following error:
W/System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
This is part of the Json: "tags": ["GLUTEN FREE", "NUT FREE"],
My RealmString:
public class RealmString extends RealmObject {
private String value;
public RealmString() {
}
public RealmString(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Part of the retrofited Pojo:
public class Entity extends RealmObject {
@SerializedName("tags")
private RealmList<RealmString> tags = null;
}
.. and the Deserializer:
public class StringRealmListConverter implements JsonDeserializer<RealmList<RealmString>> {
@Override
public RealmList<RealmString> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
RealmList<RealmString> realmStrings = new RealmList<>();
JsonArray ja = json.getAsJsonArray();
for (JsonElement je : ja) {
realmStrings.add((RealmString) context.deserialize(je, RealmString.class));
}
return realmStrings;
}
}
And I'm registering it here:
public Gson provideGson() {
return new GsonBuilder()
.registerTypeAdapter(Food.class, new FoodDeserializer())
.registerTypeAdapter(new TypeToken<RealmList<RealmString>>() {}.getType(),
new StringRealmListConverter())
.create();
}
edit Here's the FoodDeserializer. It's in this mess because we had to use Composition over Inheritance in order to please the Realm gods:
public class FoodDeserializer implements JsonDeserializer<Food> {
public static final String TAG = FoodDeserializer.class.getSimpleName();
Gson mHelperGson;
public FoodDeserializer() {
mHelperGson = new GsonBuilder().create();
}
@Override
public Food deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String type = json.getAsJsonObject().get("responseType").getAsString();
switch (type) {
case "Platter":
return parsePlatter(json);
case "FoodItem":
return parseFoodItem(json);
default:
return null;
}
}
private PlatterEntity parsePlatter(JsonElement json) {
FoodEntity food = mHelperGson.fromJson(json, new TypeToken<FoodEntity>() {
}.getType());
ArrayList<FoodItemEntity> items = new ArrayList<>();
JsonElement je1 = json.getAsJsonObject().get("items");
if (je1 != null) {
JsonArray list = je1.getAsJsonArray();
if (list != null) {
items = mHelperGson.fromJson(list.toString(), new TypeToken<List<FoodItemEntity>>() {
}.getType());
}
}
return new PlatterEntity(food, items);
}
private FoodItemEntity parseFoodItem(JsonElement json) {
FoodEntity food = mHelperGson.fromJson(json, new TypeToken<FoodEntity>() {
}.getType());
Boolean readyToEat = null;
JsonElement je1 = json.getAsJsonObject().get("readyToEat");
if (je1 != null) {
readyToEat = je1.getAsBoolean();
}
String heatingInstructions = null;
JsonElement je2 = json.getAsJsonObject().get("heatingInstructions");
if (je2 != null) {
heatingInstructions = je2.getAsString();
}
ArrayList<IngredientEntity> ingredients = new ArrayList<>();
JsonElement je3 = json.getAsJsonObject().get("ingredients");
if (je3 != null) {
JsonArray list = je3.getAsJsonArray();
if (list != null) {
ingredients = mHelperGson.fromJson(list.toString(), new TypeToken<List<IngredientEntity>>() {
}.getType());
}
}
NutritionEntity foodNutritions = mHelperGson.fromJson(json, new TypeToken<NutritionEntity>() {
}.getType());
return new FoodItemEntity(food, readyToEat, heatingInstructions, ingredients, foodNutritions);
}
}
I would like to use a JsonDeserializer
over TypeAdapter
, but any help will be appreciated, thanks!
回答1:
Turns out my feelings were right. I had to add the StringRealmListConverter
to the FoodDeserializable
constructor, like this:
public FoodDeserializer() {
mHelperGson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<RealmList<RealmString>>() {
}.getType(),
new StringRealmListConverter())
.create();
}
回答2:
You can use the JsonDeserializationContext
(passed as the second parameter to your deserialize
function) to deserialize the RealmString
correctly. The context
knows how to deserialize all your custom types that are registered with the current Gson instance. See the documentation for JsonDeserializationContext
here: https://google.github.io/gson/apidocs/com/google/gson/JsonDeserializationContext.html.
The reason it doesn't work with your current code is because you're creating a new Gson instance in FoodDeserializer
which doesn't know about the custom deserializer for RealmString
.
来源:https://stackoverflow.com/questions/37727315/error-deserializing-a-reallistrealmstring-into-liststring