Gson将List <String>反序列化为realmList <RealmString>

avi*_*vid 25 java android realm gson

我正在使用gson进行改造,将我的json反序列化为领域对象.这在大多数情况下都非常有效.处理时遇到麻烦

RealmList(String(或任何其他基本数据类型))

由于Realm不支持RealmList,其中E不扩展Realm对象,我将String包装在RealmObject中.

public class RealmString extends RealmObject {
  private String val;

  public String getValue() {
    return val;
  }

  public void setValue(String value) {
    this.val = value;
  }
}
Run Code Online (Sandbox Code Playgroud)

我的领域对象如下

    public class RealmPerson extends RealmObject {
    @PrimaryKey
    private String userId;
    ...
    private RealmList<RealmString> stringStuff;
    private RealmList<SimpleRealmObj> otherStuff;

    <setters and getters>
   }
Run Code Online (Sandbox Code Playgroud)

SimpleRealmObj工作正常,因为它只有String元素

    public class SimpleRealmObj extends RealmObject {
    private String foo;
    private String bar;
       ...
    }
Run Code Online (Sandbox Code Playgroud)

如何反序列化stringStuff?我尝试使用gson TypeAdapter

public class RealmPersonAdapter extends TypeAdapter<RealmPerson> {
    @Override
    public void write(JsonWriter out, RealmPerson value) throws IOException {
        out.beginObject();
        Log.e("DBG " + value.getLastName(), "");
        out.endObject();
    }

    @Override
    public RealmPerson read(JsonReader in) throws IOException {
        QLRealmPerson rList = new RealmPerson();
        in.beginObject();
        while (in.hasNext()) {
            Log.e("DBG " + in.nextString(), "");
        }
        in.endObject();

        return rList;
    }
Run Code Online (Sandbox Code Playgroud)

但是我仍然遇到了IllegalStateException

2334-2334/com.qualcomm.qlearn.app E // PersonService.java:71:main com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:预期字符串但在第1行第3行路径$为NAME.

我之前尝试过RealmList,RealmString适配器无济于事.到目前为止,我设法找到的唯一解决方法是https://github.com/realm/realm-java/issues/620#issuecomment-66640786 任何更好的选择?

Vic*_*ani 32

最好是使用JsonSerializerJsonDeserializer,而不是TypeAdapterRealmObject的,因为两个原因,:

  1. 它们允许您将(de)序列化委托RealmObject给默认的Gson(de)序列化程序,这意味着您不需要自己编写样板文件.

  2. 在Gson 2.3.1中有一个奇怪的错误可能导致StackOverflowError反序列化过程中(我TypeAdapter自己尝试了这个方法并遇到了这个错误).

这是如何(替换Tag你的RealmObject班级):

(注:context.serializecontext.deserialize下面是等价于gson.toJsongson.fromJson,这意味着我们并不需要解析Tag类的自己.)

解析器+序列化器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;
    }

}
Run Code Online (Sandbox Code Playgroud)

标签类:

@RealmClass
public class Tag extends RealmObject {
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用Gson注册转换器类:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(new TypeToken<RealmList<Tag>>() {}.getType(),
                new TagRealmListConverter())
        .create();
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说仍然不起作用:`java.lang.IllegalStateException:预期BEGIN_OBJECT但是在`tags.add((RealmString)context.deserialize(je,RealmString.class))行中是STRING`;` (2认同)

iRu*_*uth 5

错误消息" Expected a string but was NAME"可以通过检索JsonReader实际json对象(String在您的情况下是一个)之前的json对象的名称来解决.

您可以查看JsonReaderAndroid文档.它有详细的解释和代码片段.您还可以查看readMessage文档中示例代码段中的方法.

我已经将你的read方法修改为我认为它应该是的.注意:我没有测试代码,因此可能会有一些小错误.

@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;
}
Run Code Online (Sandbox Code Playgroud)

如果这有帮助,请告诉我.