Error deserializing a RealList<RealmString> Into List<String>

我的未来我决定 提交于 2019-12-23 02:20:42

问题


Due to Realm inability to work with promotive types, which include Strings, 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!