J'utilise retrofit avec gson pour désérialiser mon json en objets du royaume. Cela fonctionne très bien pour la plupart. Des problèmes surgissent lorsqu'il s'agit de
RealmList (String (ou tout autre type de données de base))
Etant donné que Realm ne prend pas en charge RealmList où E n’étend pas l’objet Realm, j’enveloppe String dans un RealmObject.
public class RealmString extends RealmObject {
private String val;
public String getValue() {
return val;
}
public void setValue(String value) {
this.val = value;
}
}
Mon objet de royaume est comme ci-dessous
public class RealmPerson extends RealmObject {
@PrimaryKey
private String userId;
...
private RealmList<RealmString> stringStuff;
private RealmList<SimpleRealmObj> otherStuff;
<setters and getters>
}
SimpleRealmObj fonctionne bien car il ne contient que des éléments String
public class SimpleRealmObj extends RealmObject {
private String foo;
private String bar;
...
}
Comment puis-je désérialiser stringStuff? J'ai essayé d'utiliser un 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;
}
Cependant, je frappe toujours à IllegalStateException
2334-2334/com.qualcomm.qlearn.app E // PersonService.Java: 71 main com.google.gson.JsonSyntaxException: Java.lang.IllegalStateException: chaîne attendue, mais NOM à la ligne 1 colonne 3 chemin $.
J'ai essayé RealmList, l'adaptateur RealmString plus tôt en vain .. La seule solution de rechange que j'ai réussi à trouver jusqu'à présent est https://github.com/realm/realm-Java/issues/620#issuecomment-66640786 De meilleures options?
Le message d'erreur "Expected a string but was NAME
" peut être résolu en récupérant le nom de l'objet json dans la JsonReader
avant l'objet json (qui est une String
dans votre cas).
Vous pouvez consulter la documentation sur Android pour JsonReader . Il a l'explication détaillée et l'extrait de code. Vous pouvez également consulter la méthode readMessage
dans l'exemple de code extrait de la documentation.
J'ai modifié votre méthode read
à ce que je pense qu'elle devrait être. NOTE: Je n'ai pas testé le code, il peut donc y avoir des erreurs mineures.
@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;
}
Faites-moi savoir si cela aide.
Il est préférable d'utiliser JsonSerializer
et JsonDeserializer
plutôt que TypeAdapter
pour votre RealmObject
, pour deux raisons:
Ils vous permettent de déléguer la (dé) sérialisation de votre RealmObject
au sérialiseur Gson (de) par défaut, ce qui signifie que vous n'avez pas besoin d'écrire le passe-passe vous-même.
Il y a un bogue étrange dans Gson 2.3.1 qui pourrait causer un StackOverflowError
pendant la désérialisation (j'ai essayé l'approche TypeAdapter
moi-même et j'ai rencontré ce bogue).
Voici comment (remplacez Tag
par votre classe RealmObject
):
(NOTE que context.serialize
et context.deserialize
ci-dessous sont équivalents à gson.toJson
et gson.fromJson
, ce qui signifie que nous n'avons pas besoin d'analyser la classe Tag
nous-mêmes.)
Analyseur + sérialiseur pour 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;
}
}
Classe de tag:
@RealmClass
public class Tag extends RealmObject {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Puis enregistrez votre classe de convertisseur avec Gson:
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<RealmList<Tag>>() {}.getType(),
new TagRealmListConverter())
.create();
Mon gson typeAdapter était le coupable . L'erreur ci-dessus a été vue car je ne désérialisais pas correctement le json dans RealmPerson, le premier champ n'est pas une chaîne, d'où
in.nextString ()
était borking.
J'ai regardé un exemple de code et cela m'a frappé, je n'ai pas eu à utiliser
in.beginObject () et in.endObject ()
désérialiser une chaîne. Le code ci-dessous fonctionne.
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;
}
}
J'espère que ça aide quelqu'un.
j'ai besoin d'un sérialiseur et d'un désérialiseur jackson pour la conversion d'arrayliste en liste de domaines