java Gson 将 List<String> 反序列化为 realmList<RealmString>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28733024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Gson deserialization of List<String> into realmList<RealmString>
提问by avid
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
我正在使用 gson 的改造将我的 json 反序列化为领域对象。这在大多数情况下非常有效。处理时出现问题
RealmList(String(or any other basic data type))
RealmList(String(或任何其他基本数据类型))
Since Realm doesnt support RealmList where E doesnt extend Realm object, I wrapped String in a RealmObject.
由于 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;
}
}
My realm Object is as below
我的领域对象如下
public class RealmPerson extends RealmObject {
@PrimaryKey
private String userId;
...
private RealmList<RealmString> stringStuff;
private RealmList<SimpleRealmObj> otherStuff;
<setters and getters>
}
SimpleRealmObj works fine as it only has String elements
SimpleRealmObj 工作正常,因为它只有 String 元素
public class SimpleRealmObj extends RealmObject {
private String foo;
private String bar;
...
}
How can I deserialize stringStuff? I tried using a gson TypeAdapter
如何反序列化 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;
}
However I still hit the IllegalStateException
但是我仍然遇到了 IllegalStateException
2334-2334/com.qualcomm.qlearn.app E//PersonService.java:71﹕ main com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was NAME at line 1 column 3 path $.
2334-2334/com.qualcomm.qlearn.app E//PersonService.java:71: main com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 需要一个字符串,但在第 1 行第 3 列路径 $.
I tried RealmList, RealmString adapter earlier to no avail. The only workaround I managed to find so far is https://github.com/realm/realm-java/issues/620#issuecomment-66640786Any better options?
我之前尝试过 RealmList、RealmString 适配器无济于事。到目前为止我设法找到的唯一解决方法是https://github.com/realm/realm-java/issues/620#issuecomment-66640786 还有更好的选择吗?
采纳答案by iRuth
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).
Expected a string but was NAME
可以通过JsonReader
在实际 json 对象(String
在您的情况下为 a )之前检索 json 对象的名称来解决错误消息“ ” 。
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.
您可以查看JsonReader的Android 文档。它有详细的解释和代码片段。您还可以查看readMessage
文档中示例代码片段中的方法。
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.
我已将您的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;
}
Let me know if this helps.
如果这有帮助,请告诉我。
回答by Vicky Chijwani
It is betterto use JsonSerializer
and JsonDeserializer
rather than TypeAdapter
for your RealmObject
, because of 2 reasons:
最好使用JsonSerializer
andJsonDeserializer
而不是TypeAdapter
你的RealmObject
,因为有两个原因:
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.There's a weird bug in Gson 2.3.1that might cause a
StackOverflowError
during deserialization (I tried theTypeAdapter
approach myself and encountered this bug).
它们允许您将(反)序列化委托
RealmObject
给默认的 Gson(反)序列化程序,这意味着您无需自己编写样板。Gson 2.3.1中有一个奇怪的错误,可能会
StackOverflowError
在反序列化期间导致 a (我TypeAdapter
自己尝试过这种方法并遇到了这个错误)。
Here's how (replace Tag
with your RealmObject
class):
这是方法(替换Tag
为您的RealmObject
课程):
(NOTEthat context.serialize
and context.deserialize
below are equivalent to gson.toJson
and gson.fromJson
, which means we don'tneed to parse the Tag
class ourselves.)
(注:这context.serialize
和context.deserialize
下面是等价于gson.toJson
和gson.fromJson
,这意味着我们并不需要解析Tag
类的自己。)
Parser + serializer for RealmList<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;
}
}
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 gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<RealmList<Tag>>() {}.getType(),
new TagRealmListConverter())
.create();
回答by avid
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
我的 gson typeAdapter 是罪魁祸首。出现上述错误是因为我没有正确地将 json 反序列化为 RealmPerson,第一个字段不是字符串,因此
in.nextString()
in.nextString()
was borking.
很无聊。
I looked at some example code and it hit me, I didnt have to use
我查看了一些示例代码,它击中了我,我不必使用
in.beginObject() and in.endObject()
in.beginObject() 和 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.
希望这可以帮助某人。
回答by avez raj
i need a Hymanson serializer and deserializer for the Converting Arraylist to RealmList
我需要一个 Hymanson 序列化器和反序列化器来将 Arraylist 转换为 RealmList