Gson 将 List<String> 反序列化为 realmList<RealmString>
Posted
技术标签:
【中文标题】Gson 将 List<String> 反序列化为 realmList<RealmString>【英文标题】:Gson deserialization of List<String> into realmList<RealmString> 【发布时间】:2015-04-28 06:33:50 【问题描述】:我正在使用带有 gson 的改造来将我的 json 反序列化为领域对象。这在大多数情况下都非常有效。处理时出现问题
RealmList(String(或任何其他基本数据类型))
由于 Realm 不支持 E 不扩展 Realm 对象的 RealmList,我将 String 包装在 RealmObject 中。
public class RealmString extends RealmObject
private String val;
public String getValue()
return val;
public void setValue(String value)
this.val = value;
我的领域对象如下
public class RealmPerson extends RealmObject
@PrimaryKey
private String userId;
...
private RealmList<RealmString> stringStuff;
private RealmList<SimpleRealmObj> otherStuff;
<setters and getters>
SimpleRealmObj 工作正常,因为它只有字符串元素
public class SimpleRealmObj extends RealmObject
private String foo;
private String bar;
...
如何反序列化 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;
但是我还是遇到了 IllegalStateException
2334-2334/com.qualcomm.qlearn.app E//PersonService.java:71: 主要 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 应为字符串,但名称位于第 1 行第 3 列路径$。
我之前尝试过RealmList,RealmString 适配器无济于事。 到目前为止,我设法找到的唯一解决方法是https://github.com/realm/realm-java/issues/620#issuecomment-66640786 有更好的选择吗?
【问题讨论】:
【参考方案1】:It is better 使用JsonSerializer
和JsonDeserializer
而不是TypeAdapter
作为您的RealmObject
,原因有两个:
它们允许您将 RealmObject
的序列化(反)序列化委托给默认的 Gson(反)序列化程序,这意味着 您不需要自己编写样板。
有a weird bug in Gson 2.3.1 可能会在反序列化期间导致***Error
(我自己尝试了TypeAdapter
方法并遇到了这个错误)。
方法如下(将 Tag
替换为您的 RealmObject
类):
(注意下面的context.serialize
和context.deserialize
等价于gson.toJson
和gson.fromJson
,这意味着我们不需要解析@ 987654340@自己上课。)
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;
标签类:
@RealmClass
public class Tag extends RealmObject
private String value;
public String getValue()
return value;
public void setValue(String value)
this.value = value;
然后用 Gson 注册你的转换器类:
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<RealmList<Tag>>() .getType(),
new TagRealmListConverter())
.create();
【讨论】:
你的解决方案是最好的! 此解决方案效果最佳,无需其他解决方案中推荐的样板代码。 这对我仍然不起作用:java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
在tags.add((RealmString) context.deserialize(je, RealmString.class));
行中
@HenriquedeSousa 该错误意味着您收到的 JSON 在某种程度上与您的代码不匹配。您的RealmString
类的定义方式与@avid 的原始问题完全相同吗?还有你的 JSON 是什么样的?
@VickyChijwani 我发布了另一个问题,如果你愿意,可以帮助我,谢谢:***.com/questions/37727315/…【参考方案2】:
错误消息“Expected a string but was NAME
”可以通过在实际 json 对象(在您的情况下为 String
)之前检索 JsonReader
中的 json 对象的名称来解决。
您可以查看android documentation for JsonReader。它有详细的解释和代码sn-p。也可以看看文档中示例代码sn-p中的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;
如果这有帮助,请告诉我。
【讨论】:
谢谢@iRuth。这确实是反序列化 json blob 并回答原始问题的方法。我会将其标记为正确答案。对于只想反序列化领域字符串的其他人,请在下面查看我的答案。【参考方案3】:我的 gson typeAdapter 是罪魁祸首。 上面的错误被认为是我没有正确地将 json 反序列化为 RealmPerson,第一个字段不是字符串,因此
in.nextString()
很无聊。
我看了一些示例代码,它击中了我,我不必使用
in.beginObject() 和 in.endObject()
反序列化一个字符串。以下代码有效。
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;
希望这对某人有所帮助。
【讨论】:
这是缺少的链接!我将所有模型转换为使用原始类型和 RealmString 对象,设置一个排除策略,如下所示:***.com/questions/32434377/…,然后实现了这个 RealmString TypeAdapter,一切正常!谢谢【参考方案4】:我需要一个用于将 Arraylist 转换为 RealmList 的 jackson 序列化器和反序列化器
【讨论】:
以上是关于Gson 将 List<String> 反序列化为 realmList<RealmString>的主要内容,如果未能解决你的问题,请参考以下文章
当从共享prefs获取时,GSON将先前存储的List转换为LinkedTreeMaps的ArrayList
在 Java 中将 JSON 转换为 List<List<String>>