Comment implémenter type TypeAdapterFactory dans Gson?
La principale méthode de création est générique. Pourquoi?
La méthode d'enregistrement registerTypeAdapterFactory () ne reçoit pas de type un argument de type. Alors, comment Gson
sait-il quelles classes sont traitées par l'usine?
Dois-je implémenter une usine pour plusieurs classes, ou puis-je en implémenter une pour plusieurs classes?
Si j'implémente une usine pour plusieurs classes, que dois-je retourner en cas d'argument de type hors domaine?
Lorsque vous enregistrez un adaptateur de type standard (GsonBuilder.registerTypeAdapter
), il génère uniquement un adaptateur de type pour cette classe spécifique. Par exemple:
public abstract class Animal { abstract void speak(); }
public class Dog extends Animal {
private final String speech = "woof";
public void speak() {
System.out.println(speech);
}
}
// in some gson related method
gsonBuilder.registerTypeAdapter(Animal.class, myTypeAdapterObject);
Gson g = gsonBuilder.create();
Dog dog = new Dog();
System.out.println(g.toJson(dog));
Si vous avez fait cela, alors Gson
utilisera pas votre myTypeAdapterObject
, il utilisera l'adaptateur de type par défaut pour Object
.
Alors, comment pouvez-vous créer un objet adaptateur de type capable de convertir N'IMPORTE QUELLE sous-classe Animal
en Json? Créez un TypeAdapterFactory
! La fabrique peut correspondre en utilisant le type générique et la classe TypeToken
. Vous devez retourner null si votre TypeAdapterFactory
ne sait pas comment gérer un objet de ce type.
L'autre chose TypeAdapterFactory
peut être utilisée, c'est que vous ne pouvez pas CHAÎNER les adaptateurs d'une autre manière. Par défaut, Gson ne passe pas votre instance Gson
dans les méthodes read
ou write
de TypeAdapter
. Donc, si vous avez un objet comme:
public class MyOuterClass {
private MyInnerClass inner;
}
Il n'y a aucun moyen d'écrire votre TypeAdapter<MyOuterClass>
qui sait utiliser votre TypeAdapter<MyInnerClass>
sans utiliser le TypeAdapterFactory
. Le TypeAdapterFactory.create
la méthode PASSE l'instance Gson
, qui vous permet d'enseigner votre TypeAdapter<MyOuterClass>
comment sérialiser le champ MyInnerClass
.
Généralement, voici une bonne façon standard de commencer à écrire une implémentation d'un TypeAdapterFactory
:
public enum FooAdapterFactory implements TypeAdapterFactory {
INSTANCE; // Josh Bloch's Enum singleton pattern
@SuppressWarnings("unchecked")
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (!Foo.class.isAssignableFrom(type.getRawType())) return null;
// Note: You have access to the `gson` object here; you can access other deserializers using gson.getAdapter and pass them into your constructor
return (TypeAdapter<T>) new FooAdapter();
}
private static class FooAdapter extends TypeAdapter<Foo> {
@Override
public void write(JsonWriter out, Foo value) {
// your code
}
@Override
public Foo read(JsonReader in) throws IOException {
// your code
}
}
}