2017-03-10 1 views
6

Je souhaite ajouter un sérialiseur et un désérialiseur personnalisés pour JSR 363 javax.measure.Quantity<Q extends Quantity<Q>>, qui encapsule fondamentalement une «valeur» et une «unité». La création du sérialiseur (extends JsonSerializer<Quantity<?>>) et du désérialiseur (extends StdDeserializer<Quantity<?>>) est facile.La signature du module Jackson empêche les ajouts de sérialiseurs pour les types génériques auto-référencés

Mais ce n'est pas facile de les enregistrer. Pour les désérialiseurs, c'est OK. regardez la signature:

SimpleModule.addDeserializer(Class<T> type, JsonDeserializer<? extends T> deser) 

Notez que le désérialiseur permet d'étendre le type générique. Donc, je peux le faire:

module.addDeserializer(Quantity.class, new MyQuantityJsonDeserializer()); 

Mais le sérialiseur est une autre histoire; regardez la signature pour son enregistrement:

SimpleModule.addSerializer(Class<? extends T> type, JsonSerializer<T> ser) 

Oh, la douleur que cela provoque en raison du type générique restreint. Je ne peux pas le faire:

module.addSerializer(Quantity.class, new MyQuantityJsonSerializer()); 

C'est parce que Quantity.class ne me donner un Class<Quantity<Q extends Quantity<Q>>. Et il n'y a pas de distribution facile sans introduire une variable générique arbitraire dans la méthode du module et en utilisant des distributions acrobatiques. Même cela ne fonctionnera pas:

module.addSerializer((Class<Quantity<?>>) Quantity.class, new MyQuantityJsonSerializer()); 

Le meilleur que je suis en mesure de faire est de faire ma classe sérialiseur QuantityJsonSerializer<Q extends Quantity<Q>> extends JsonSerializer<Q>, puis dans le module enregistrer comme le type brut:

@SuppressWarnings({"rawtypes", "unchecked"}) 
final JsonSerializer<Quantity> quantitySerializer = 
    (JsonSerializer<Quantity>) new MyQuantityJsonSerializer(); 
module.addSerializer(Quantity.class, quantitySerializer); 

Ugh, comment est-ce laid? Mais c'est l'une des seules façons que je peux trouver pour le faire fonctionner, et j'ai dû faire plus de gymnastique pour supprimer les avertissements.

Sûrement SimpleModule.addSerializer() aurait pu être un peu plus flexible sur ses paramètres génériques, analogue à SimpleModule.addDeserializer()?

Je signale ceci ici parce que le projet Jackson a dit de rapporter des bogues ici --- et je demande également de meilleures idées de contournement. Merci.

+0

Do vous avez besoin d'utiliser des génériques? – mikep

+0

Vous pouvez lancer la classe avec une distribution en deux parties, quelque chose comme '(Classe >) (Classe ) Quantity.class' ou' (Classe >) (Classe ) Quantity.class'. Le design de 'Class' est vraiment très mauvais pour ce genre de choses. Java doit le remplacer par quelque chose comme ['TypeToken'] (http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/reflect/TypeToken.html). Les problèmes ne disparaîtront pas tant qu'il est utile d'enregistrer un type de gestionnaire avec un type particulier. La réponse de ck1 suggère que vous n'avez pas besoin de faire le casting dans ce cas, cependant. – Radiodef

+0

Mais qu'en est-il de l'incohérence dans les méthodes 'addSerializer()' et addDeserializer() '? Pourquoi y a-t-il une incohérence? Où dois-je déposer un problème pour que Jackson puisse résoudre ce problème? Ou y a-t-il une raison pour que l'incohérence reste? –

Répondre

3

En SimpleModule il y a une version surchargée de addSerializer():

public SimpleModule addSerializer(JsonSerializer<?> ser) 

qui permet cela fonctionne:

module.addSerializer(new MyQuantityJsonSerializer()); 

aussi longtemps que vous définissez votre sérialiseur comme:

public class MyQuantityJsonSerializer extends StdSerializer<Quantity<?>> { 
    public MyQuantityJsonSerializer() { 
     // Note: second argument here is ignored. 
     super(Quantity.class, false); 
    } 

    @Override 
    public void serialize(Quantity<?> value, JsonGenerator gen, SerializerProvider serializers) throws IOException { 
     // Serialize value here... 
    } 
}