Ошибка десериализации RealList<RealmString> в список<String>
Из-за невозможности Realm работать с промо-типами, которые включают String
с, я пытаюсь реализовать JsonDeserializer
как в этом вопросе.
Проблема в том, что я сбит с толку, почему я получаю следующую ошибку:
W / System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: ожидается BEGIN_OBJECT, но было STRING
Это часть Json: "tags": ["GLUTEN FREE", "NUT FREE"],
Моя 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;
}
}
Часть модифицированного Pojo:
public class Entity extends RealmObject {
@SerializedName("tags")
private RealmList<RealmString> tags = null;
}
.. и десериализатор:
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;
}
}
И я регистрирую это здесь:
public Gson provideGson() {
return new GsonBuilder()
.registerTypeAdapter(Food.class, new FoodDeserializer())
.registerTypeAdapter(new TypeToken<RealmList<RealmString>>() {}.getType(),
new StringRealmListConverter())
.create();
}
редактировать Вот FoodDeserializer. Именно в этом беспорядке, потому что мы должны были использовать Композицию вместо Наследования, чтобы угодить богам Царства:
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);
}
}
Я хотел бы использовать JsonDeserializer
над TypeAdapter
, но любая помощь будет оценена, спасибо!
2 ответа
Оказывается, мои чувства были правы. Я должен был добавить StringRealmListConverter
к FoodDeserializable
конструктор, вот так:
public FoodDeserializer() {
mHelperGson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<RealmList<RealmString>>() {
}.getType(),
new StringRealmListConverter())
.create();
}
Вы можете использовать JsonDeserializationContext
(передается как второй параметр вашему deserialize
функция) для десериализации RealmString
правильно. context
знает, как десериализовать все ваши пользовательские типы, которые зарегистрированы в текущем экземпляре Gson. Смотрите документацию для JsonDeserializationContext
здесь: https://google.github.io/gson/apidocs/com/google/gson/JsonDeserializationContext.html.
Причина, по которой он не работает с вашим текущим кодом, заключается в том, что вы создаете новый экземпляр Gson в FoodDeserializer
который не знает о пользовательских десериализатора для RealmString
,