web-dev-qa-db-fra.com

Le constructeur par défaut sans argument est-il obligatoire pour Gson?

Guide de l'utilisateur Gson indique que nous devons définir le constructeur par défaut sans argument pour que toute classe fonctionne correctement avec Gson. Plus encore, dans la classe javadoc de la classe InstanceCreator de Gson, cette exception sera levée si nous essayons de désérialiser l'instance de la classe manquant au constructeur par défaut et nous devrait = utilisez InstanceCreator dans de tels cas. Cependant, j'ai essayé de tester l'utilisation de Gson avec une classe sans constructeur par défaut et le travail de sérialisation et de désérialisation sans aucun problème.

Voici le morceau de code pour la désérialisation. Une classe sans constructeur non-args:

public class Mushroom {
    private String name;
    private double diameter;

    public Mushroom(String name, double diameter) {
        this.name = name;
        this.diameter = diameter;
    }

    //equals(), hashCode(), etc.
}

et un test:

@Test
public void deserializeMushroom() {
    assertEquals(
            new Mushroom("Fly agaric", 4.0),
            new Gson().fromJson(
                    "{name:\"Fly agaric\", diameter:4.0}", Mushroom.class));
}

qui fonctionne bien.

Donc ma question est: pourrais-je réellement utiliser Gson sans avoir besoin d'un constructeur par défaut ou il y a des circonstances où cela ne fonctionnera pas?

51
raindev

Depuis Gson 2.3.1.

Indépendamment de ce que dit la documentation de Gson, si votre classe n'a pas de constructeur sans argument et que vous n'avez enregistré aucun objet InstanceCreater, elle créera un ObjectConstructor (qui construit votre objet ) avec un UnsafeAllocator qui utilise Reflection pour obtenir la méthode allocateInstance de la classe Sun.misc.Unsafe pour créer votre instance de classe.

Cette classe Unsafe contourne le manque de constructeur sans argument et a de nombreuses autres utilisations dangereuses . allocateInstance états

Allouez une instance mais n'exécutez aucun constructeur. Initialise la classe si elle ne l'a pas encore été.

Il n'a donc pas réellement besoin d'un constructeur et contournera votre constructeur à deux arguments. Voir quelques exemples ici .

Si vous avez un constructeur sans argument, Gson utilisera un ObjectConstructor qui utilise cette valeur par défaut Constructor en appelant

yourClassType.getDeclaredConstructor(); // ie. empty, no-args

Mes 2 cents: Suivez ce que dit Gson et créez vos classes avec un constructeur sans argument ou enregistrez un InstanceCreator. Vous pourriez vous retrouver dans une mauvaise position en utilisant Unsafe.

86

Il y a une bonne solution dans la bibliothèque Jackson comme décrit ici:

https://stackoverflow.com/a/11838468/285472

Le but est d'indiquer au sérialiseur via la fonction fonction Mix-Ins les champs JSON à utiliser lors de l'utilisation du constructeur avec des arguments.

Si cette entité fait partie d'une bibliothèque externe, vous pouvez "annoter à distance" avec la fonction Créateur .

1
thomas.mc.work