【问题标题】:Error deserializing a RealList<RealmString> Into List<String>将 RealList<RealmString> 反序列化为 List<String> 时出错
【发布时间】:2016-06-09 13:25:15
【问题描述】:

由于 Realm 无法使用促销类型,包括 Strings,我正在尝试实现 JsonDeserializer,就像 in this question 一样。

问题是我对为什么会收到以下错误感到困惑:

W/System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 应为 BEGIN_OBJECT 但为 STRING

这是 Json 的一部分:"tags": ["GLUTEN FREE", "NUT FREE"],

我的领域字符串:

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();
}

edit 这是 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,但我们将不胜感激,谢谢!

【问题讨论】:

  • realmStrings.add((RealmString) context.deserialize(je, RealmString.class)); 为什么? ...您可以使用realmStrings.add(new RealmString(je.getAsString()));
  • 或者使用这个答案stackoverflow.com/questions/29493101/…(记得把int改成字符串)
  • 如果您不覆盖自己的反序列化器,则无法反序列化 GSON 中的 Realm 列表。
  • @Selvin 我已经用这个答案作为基础,但仍然不起作用。
  • @Alexander 我已经更新了我的答案,我认为问题是 RealmString 在 Food 对象内,这就是它没有触发我的 RealmString 反序列化器的原因!

标签: android realm realm-list


【解决方案1】:

事实证明我的感觉是对的。我必须将StringRealmListConverter 添加到FoodDeserializable 构造函数中,如下所示:

    public FoodDeserializer() {
        mHelperGson = new GsonBuilder()
            .registerTypeAdapter(new TypeToken<RealmList<RealmString>>() {
                    }.getType(),
                    new StringRealmListConverter())
            .create();
    }

【讨论】:

  • 实际上有一种更简单的方法可以做到这一点 - 请参阅我的答案。
【解决方案2】:

您可以使用JsonDeserializationContext(作为第二个参数传递给deserialize 函数)正确反序列化RealmStringcontext 知道如何反序列化所有在当前 Gson 实例中注册的自定义类型。在此处查看JsonDeserializationContext 的文档:https://google.github.io/gson/apidocs/com/google/gson/JsonDeserializationContext.html

它不适用于您当前的代码的原因是因为您在FoodDeserializer 中创建了一个 Gson 实例,它不知道RealmString 的自定义反序列化器。

【讨论】:

    猜你喜欢
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    • 2018-01-09
    • 2017-01-15
    • 2020-05-06
    • 1970-01-01
    相关资源
    最近更新 更多