Gson deserialization of List<String> into realmList<RealmString>

自古美人都是妖i 提交于 2019-11-27 07:06:46

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.

Vicky Chijwani

It is better to use JsonSerializer and JsonDeserializer rather than TypeAdapter for your RealmObject, because of 2 reasons:

  1. 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.

  2. 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();

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.

i need a jackson serializer and deserializer for the Converting Arraylist to RealmList

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