Gson deserialization of List into realmList

前端 未结 4 604
刺人心
刺人心 2020-12-01 05:18

I\'m using retrofit with gson to deserialize my json into realm objects. This works very well for the most part. Trouble arises when dealing with

Rea

相关标签:
4条回答
  • 2020-12-01 05:58

    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.

    0 讨论(0)
  • 2020-12-01 06:01

    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.

    0 讨论(0)
  • 2020-12-01 06:07

    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();
    
    0 讨论(0)
  • 2020-12-01 06:13

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

    0 讨论(0)
提交回复
热议问题