Gson désérialisation: jeu de champ final
je désérialiser un widget-hiérarchie à l'aide de gson, mais ont de la difficulté de la désérialisation final champs.
Exemple:
public final class Screen{
@Expose
private final List<WidgetDefinition> children = null;
@Expose
private final String name = null;
}
public final class AWidget implements WidgetDefinition {
@Expose
private final String name = null;
}
je suis la désérialisation d'un Écran à l'aide personnalisée deserializer pour WidgetDefinition, illustré ci-dessous. 'nom' Écran est correctement réglé, 'nom' dans AWidget reste nulle.
final class Deserializer implements JsonDeserializer<WidgetDefinition> {
public WidgetDefinition deserialize(final JsonElement json, final Type type,
final JsonDeserializationContext context) {
JsonObject jsonObject = json.getAsJsonObject();
String typeName = jsonObject.get("type").getAsString();
if (typeName.equals("awidget")) {
return context.deserialize(json, AWidget.class);
} else {
return null;
}
}
}
Edit: je me demande si elle doit faire quelque chose avec ça:
Gson 1.7 ne sérialiser la sous-classe des champs dans les éléments d'une collection. 2.0 ajoute cette information supplémentaire.
(https://sites.google.com/site/gson/gson-roadmap)
pourquoi voulez-vous désérialiser un champ final ? final est destiné à déclarer que cela ne changera pas, alors, vraiment, vous semblez être de piratage de votre propre modèle.
Je veux des objets immuables. Je ne suis pas la création de ces objets n'importe où à l'exception de l'analyse de gson, et il n'y a pas besoin de les changer par la suite. L'immuabilité est toujours mieux dans ma compréhension.
yup mais vous pouvez les rendre privés et n'offrent pas de poseurs - qui permettrait d'atteindre le même but?
Presque. Il y a quelques membres, j'ai mis en interne et je tiens à les distinguer en ayant une section finale et un non-dernière section dans mes membres. je me demandais simplement pourquoi gson se comporte comme cela.
Un peu en retard à la fête, mais je suis d'accord avec votre sentiment. C'est un interminable aggravation de moi que Java fournit pas de sérialisation capacité à manipuler des objets immuables lorsqu'ils sont donc essentiels à la simplification d'un multi-modèle de thread.
Je veux des objets immuables. Je ne suis pas la création de ces objets n'importe où à l'exception de l'analyse de gson, et il n'y a pas besoin de les changer par la suite. L'immuabilité est toujours mieux dans ma compréhension.
yup mais vous pouvez les rendre privés et n'offrent pas de poseurs - qui permettrait d'atteindre le même but?
Presque. Il y a quelques membres, j'ai mis en interne et je tiens à les distinguer en ayant une section finale et un non-dernière section dans mes membres. je me demandais simplement pourquoi gson se comporte comme cela.
Un peu en retard à la fête, mais je suis d'accord avec votre sentiment. C'est un interminable aggravation de moi que Java fournit pas de sérialisation capacité à manipuler des objets immuables lorsqu'ils sont donc essentiels à la simplification d'un multi-modèle de thread.
OriginalL'auteur Fabian Zeindl | 2011-12-02
Vous devez vous connecter pour publier un commentaire.
Gson utilise la réflexion pour définir final champs (via
.setAccessible(true)
), de sorte que le problème que vous décrivez (et autres) vient probablement de la façon dont Java poignées de finale...OriginalL'auteur Jan Chimiak
C'est un peu difficile à résoudre que le problème précis dans la question d'origine, puisque compléter un minimum de code et les exemples n'ont pas été fournies. Peut-être le suivant compréhension de la façon dont Gson instancie des objets cibles lors de la désérialisation aide.
Gson 1.7.1 et de la 2.0 à la fois le respect finale des affectations sur le terrain lors de la vanille de la désérialisation des opérations, et la première finale des affectations sur le terrain ne sont pas modifiées. Par exemple:
D'autre part, pour la création de l'instance lors de la désérialisation, depuis Gson utilise
sun.misc.Unsafe
-- et pas un constructeur, les affectations de finale champs explicitement défini dans aucun constructeur ne sont pas respectés. Par exemple:En résumé, au cours de la vanille de la désérialisation, il n'est pas possible de réaffecter une dernière cession de terrain avec toutes les données de la prochaine JSON, même si il peut sembler être possible que si le final de la cession de terrain est survenu dans un définis par l'utilisateur constructeur.**
**Je ne suis pas sûr si la JVM spec permet pour certains de la mise en œuvre de mesures de clémence, tels qu'un comportement différent de ce qui est décrit ci-dessus peut être observée lors de l'exécution sur différentes machines virtuelles java.
Accusé de réception. Puis Gson est encore plus incohérent que j'ai deviné que c'était.
OriginalL'auteur Programmer Bruce
La spécificité de la question n'est pas tout à fait correspondre le titre générique, mais j'ai eu le même problème et la question est d'un haut niveau de résultats sur Google pour moi, donc je vais répondre ici, en dépit de la question de l'âge.
De synthétiser les résultats des autres réponses ici, il semble que les dernières versions actuelles de Gson sera deserialise objets mais ne deserialise primitives si ils ont été initialisés.
Les diverses incohérences dans ce comportement était assez pour me décider à définir un type de cartes et omettre les constructeurs par défaut. Depuis Gson 2.1,
TypeAdapter
rend cela très simple. L'inconvénient est que Gson maintenant ne peut pas gérer cela automatiquement.Donné un type
Point
défini comme:Légèrement ajustée variante de l'exemple de la documentation
donne le résultat souhaité.
OriginalL'auteur mkjeldsen
J'ai tenté l'expérience avec final des champs - tout d'abord les configurer avec initialisers, par exemple:
GSON ne serait pas deserialise cela correctement.
et puis dans le constructeur...
Cela a fonctionné. C'est peut-être un compilateur Java est de l'optimisation, où la finale primitive ou une Chaîne de type de variables avec initialisers sont traités comme des conmpile-constantes de temps, sans réelles de la variable en cours de création, alors que si l'initialisation se fait dans le constructeur, une variable est créée?
OriginalL'auteur Phil Doble