Voir la solution à la fin.Analyse de Gson dans un objet contenant un JsonArray
question originale
je l'objet suivant dans mon code que je suis en train de désérialiser avec Gson.
public class Foo {
public Map<String, JSONArray> bar = new HashMap<>();
public ... other stuff
}
J'ai aussi essayé avec:
public class Foo {
public Map<String, String> bar = new HashMap<>();
public ... other stuff
}
La raison en est ici parce que le Map
sera alimentation dans les sous-modules qui pourraient être tout type de données. En interne chaque module sait comment analyser ses propres données.
sur la version JsonArray
je reçois cette erreur:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 3 column 18 path $.trigger.
et dans la version String
je reçois cette erreur:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected a string but was BEGIN_ARRAY at line 3 column 18 path $.trigger.
Ma question est:
Puis-je analyser cela sans le besoin d'un désérialisateur personnalisé? Comment?
Edit: ci-dessous sont les bits correspondants du code:
// Gson is singleton provided by Dagger2
Gson gson = new GsonBuilder().create();
// retrofit is also singleton provided by dagger
Retrofit restAdapter = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(buildOkHttpClient(context))
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return restAdapter.create(ApiService.class);
// then the Retrofit API
@GET("our path")
Observable<Foo> getFoo(a couple of values);
J'ai aussi essayé d'utiliser un MockTransport qui est directement invoquait Gson, comme suit:
Observable
.just(fooResponse)
.delay(101, TimeUnit.MILLISECONDS)
.map(new Function<String, Foo>() {
@Override public Interactions apply(String s) throws Exception {
return gson.fromJson(s, Foo.class);
}
});
et au-dessous pertinentes parties du JSON:
{
"bar": {
"type0": [
{
... object 0
}
],
"type1": [
{
... object 0
},
{
... object 1
}
]
},
"otherStuff" : {
}
}
Le j fils est sûr correctement formaté, il vient de nos serveurs et je l'ai re-vérifié sur jsonlint.com
solution :
il semble que ce n'est pas possible de le faire sans désérialiseur sur mesure. J'ai donc écrit un sérialiseur pour String, ce qui sonne mal, mais j'accepte volontiers les suggestions d'une meilleure façon de le gérer.
.registerTypeAdapter(String.class, new JsonDeserializer<String>() {
@Override
public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive()) {
return json.getAsJsonPrimitive().getAsString();
} else {
return json.toString();
}
}
})
Comment désérialiser cas 'foo'? Quelque chose comme 'gson.from (..., Foo.class)'? –
@LyubomyrShaydariv oui. exactement comme ça. Je vais mettre à jour la question avec ces détails. – Budius
Sera également utile si vous avez ajouté un exemple de json de ce que vous voulez désérialiser –