retrofit gson converter pour json imbriqué avec différents objets
J'ai structure JSON comme suit -
{
"status": true,
"message": "Registration Complete.",
"data": {
"user": {
"username": "user88",
"email": "[email protected]",
"created_on": "1426171225",
"last_login": null,
"active": "1",
"first_name": "User",
"last_name": "",
"company": null,
"phone": null,
"sign_up_mode": "GOOGLE_PLUS"
}
}
}
Ci-dessus est le format habituel . Seulement data
clé peut contenir différents types d'informations comme les user
product
invoice
etc.
Je veux garder status
message
et data
clés même dans tous les reste de réponse. data
seront traitées conformément à status
et message
sera affiché à l'utilisateur.
Donc, fondamentalement, au-dessus est le format désiré dans toutes les api. Seulement de l'information à l'intérieur de data
clé sera différente à chaque fois.
Et j'ai configuré une classe suivante et de le configurer comme gson convertisseur - MyResponse.java
public class MyResponse<T> implements Serializable{
private boolean status ;
private String message ;
private T data;
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Deserializer.java
class Deserializer<T> implements JsonDeserializer<T>{
@Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException{
JsonElement content = je.getAsJsonObject();
//Deserialize it. You use a new instance of Gson to avoid infinite recursion to this deserializer
return new Gson().fromJson(content, type);
}
}
Et l'a utilisé comme suit -
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
gsonBuilder.registerTypeAdapter(MyResponse.class, new Deserializer<MyResponse>());
...... ..... ....
restBuilder.setConverter(new GsonConverter(gsonBuilder.create()));
Interface de Service est comme suit -
@POST("/register")
public void test1(@Body MeUser meUser, Callback<MyResponse<MeUser>> apiResponseCallback);
@POST("/other")
public void test2(Callback<MyResponse<Product>> apiResponseCallback);
Problème
Je peux accéder à status
et message
champs à partir de l'intérieur de rappel. Mais l'information à l'intérieur de data
clé n'est pas analysée et le modèle comme MeUser
et Product
retourne toujours aussi vide.
Si je change de structure json à la suite du code ci-dessus fonctionne parfaitement -
{
"status": true,
"message": "Registration Complete.",
"data": {
"username": "user88",
"email": "[email protected]",
"created_on": "1426171225",
"last_login": null,
"active": "1",
"first_name": "User",
"last_name": "",
"company": null,
"phone": null,
"sign_up_mode": "GOOGLE_PLUS"
}
}
Comment je peux avoir travaillé avec spécifier la clé distinct à l'intérieur de data
de l'objet et de l'analyser avec succès ?
source d'informationauteur Gimali
Vous devez vous connecter pour publier un commentaire.
Si je peux vous suggérer de changer quelque chose dans le json, c'est que vous avez à ajouter à un nouveau champ qui définit le type de données, de sorte json doit ressembler à ci-dessous:
La
MyResponse
classe a et à de nouveaux déposéDataType
donc, il devrait ressembler à ci-dessous:La
DataType
est un enum qui définit le type de données. Vous devez passer Data.class en tant que paramètre dans le constructeur. Pour tous les types de données, vous devez créer de nouvelles classes.DataType
enum doit ressembler à ci-dessous:La desarializator Json devrait ressembler à ci-dessous:
Et lorsque vous créez
RestAdapter
dans la ligne où vous vous inscrivez Deserializator, vous devez utiliser cette :Autres classes (types de données) que vous définissez comme la norme de POJO pour Gson dans des classes séparées.
Votre problème est que la
data
attribut est défini commeT
de laquelle vous vous attendez à être de typesMeUser
Product
etc, mais est en fait d'un objet qui a intérieure attribut commeuser
. Pour résoudre ce problème, vous devez introduire un autre niveau de classes qui possède les attributs requisuser
product
invoice
etc. Ceci peut être facilement réalisé à l'aide de statique à l'intérieur des classes.Peut-être un peu hors-sujet, mais ce qui se passe si l'objet interne contient une propriété de Date? Mon TypeAdapter ressemble à ceci:
Mais en raison de l'analyse qui est faite par ce :
message.setData(new Gson().fromJson(data, message.getDataType().getType()));
Il lève une erreur à chaque fois qu'il va essayer de désérialiser la Date de la propriété. Est-il une solution?
EDIT: Marqué la réponse comme acceptée définitivement 🙂 il m'a aidé à résoudre mon problème. Mais maintenant, il y a ce problème avec la date deserializer.