java - studio - realm windows
Deserialización de Gson de la Lista<String> en realmList<RealmString> (4)
El mensaje de error " Expected a string but was NAME
" se puede resolver recuperando el nombre del objeto json en el JsonReader
antes del objeto json real (que es una String
en su caso).
Puedes echar un vistazo a la documentación de Android para JsonReader . Tiene una explicación detallada y un fragmento de código. También puede echar un vistazo al método readMessage
en el fragmento de código de ejemplo en la documentación.
He modificado su método de read
a lo que creo que debería ser. NOTA: No probé el código, por lo que puede haber algunos errores menores en él.
@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;
}
Déjeme saber si esto ayuda.
Estoy usando la adaptación con gson para deserializar mi json en objetos de reino. Esto funciona muy bien en su mayor parte. El problema surge cuando se trata de
RealmList (String (o cualquier otro tipo de datos básico))
Como Realm no admite RealmList donde E no extiende el objeto Realm, envolví String en un RealmObject.
public class RealmString extends RealmObject {
private String val;
public String getValue() {
return val;
}
public void setValue(String value) {
this.val = value;
}
}
Mi objeto de reino es el siguiente
public class RealmPerson extends RealmObject {
@PrimaryKey
private String userId;
...
private RealmList<RealmString> stringStuff;
private RealmList<SimpleRealmObj> otherStuff;
<setters and getters>
}
SimpleRealmObj funciona bien ya que solo tiene elementos de cadena
public class SimpleRealmObj extends RealmObject {
private String foo;
private String bar;
...
}
¿Cómo puedo deserializar stringStuff? Intenté usar un TypeAdapter de GSON
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;
}
Sin embargo todavía golpeo el IllegalStateException
2334-2334 / com.qualcomm.qlearn.app E // PersonService.java: 71 ﹕ main com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: se esperaba una cadena pero era NAME en la línea 1 columna 3 ruta $.
Probé RealmList, el adaptador RealmString anteriormente sin éxito. La única solución que logré encontrar hasta ahora es https://github.com/realm/realm-java/issues/620#issuecomment-66640786 Alguna opción mejor?
Mi gson typeAdapter fue el culpable. El error anterior se vio como no estaba deserializando el json en RealmPerson correctamente, el primer campo no es una cadena, por lo tanto
in.nextString ()
fue borking
Miré un código de ejemplo y me di cuenta, no tuve que usar
in.beginObject () y in.endObject ()
Deserializar una cadena. El código de abajo funciona.
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;
}
}
Espero que esto ayude a alguien.
Necesito un serializador y deserializador jackson para convertir Arraylist a RealmList
Es mejor usar JsonSerializer
y JsonDeserializer
lugar de TypeAdapter
para su RealmObject
, debido a 2 razones:
Le permiten delegar (des) la serialización para su
RealmObject
al serializador Gson (de) predeterminado, lo que significa que no necesita escribir la placa de calderín usted mismo .Hay un error extraño en Gson 2.3.1 que podría causar un
Error
durante la deserialización (probé el enfoqueTypeAdapter
y encontré este error).
Aquí le indicamos cómo (reemplace la Tag
con su clase RealmObject
):
( context.serialize
que context.serialize
y context.deserialize
continuación son equivalentes a gson.toJson
y gson.fromJson
, lo que significa que no necesitamos analizar la clase Tag
nosotros mismos).
Analizador + serializador para 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;
}
}
Clase de etiqueta:
@RealmClass
public class Tag extends RealmObject {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Luego registre su clase de convertidor con Gson:
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<RealmList<Tag>>() {}.getType(),
new TagRealmListConverter())
.create();