2010-11-10 5 views
4

J'ai une classe héritée, avec beaucoup de doubles champs publics. Tous les champs doubles sont initialisés avec Double.MAX_VALUE pour indiquer qu'ils sont vides. (La sérialisation héritée est codée pour ignorer le champ et non sérialiser si le champ est égal à Double.MAX_VALUE).JAXB: Comment personnaliser la sérialisation Xml de champs doubles

Nous essayons maintenant de sérialiser cette classe en Xml en utilisant JAXB Marshaller. Cela fonctionne bien, sauf que nous voulons empêcher la génération de Xml pour les champs qui correspondent à Double.MAX_VALUE.

Nous n'utilisons pas de schéma JAXB séparé, mais marquons simplement nos classes avec diverses annotations javax.xml.bind.annotation. Si un schéma est utilisé, vous pouvez ajouter un élément <javaType> pour spécifier un convertisseur DataType personnalisé. Est-il possible de faire cela en utilisant Annotations ou par programmation?

Après avoir essayé l'approche recommandée ci-dessous, je ne peux toujours pas XmlAdapter ramassé:

@XmlJavaTypeAdapters({ 
@XmlJavaTypeAdapter(value=EmptyDoubleValueHandler.class, type=Double.class), @XmlJavaTypeAdapter(value=EmptyDoubleValueHandler.class, type=double.class)}) 
package tta.penstock.data.iserver; 

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; 

Ma première classe de niveau est: tta.penstock.data.iserver.OrderBlotter, qui contient une liste de TTA. penstock.data.iserver.OrderResponseWrappers qui s'étend com.eztech.OrderResponse. Tous les champs doubles sont contenus dans com.eztech.OrderResponse.

Mon code de test unitaire effectue les opérations suivantes:

JAXBContext context = JAXBContext.newInstance(new Class[] { OrderBlotter.class, OrderResponseWrapper.class, OrderResponse.class}); 

Marshaller marshaller = context.createMarshaller(); 
StringWriter stringWriter = new StringWriter(); 
marshaller.marshal(blotter, stringWriter); 
System.out.println("result xml=\n" + stringWriter.toString()); 

Mais les doubles valeurs ne sont pas encore traitées par le XmlAdapter. Je sais qu'il me manque quelque chose de basique, mais je ne suis pas sûr de ce que c'est.

Répondre

9

Vous pouvez utiliser un XMLAdapter:

Le XMLAdapter

package example; 

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class DoubleAdapter extends XmlAdapter<Double, Double>{ 

    @Override 
    public Double unmarshal(Double v) throws Exception { 
     return v; 
    } 

    @Override 
    public Double marshal(Double v) throws Exception { 
     if(Double.MAX_VALUE == v) { 
      return null; 
     } else { 
      return v; 
     } 
    } 

} 

Le modèle objet

package example; 

import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlRootElement 
public class Root { 

    @XmlJavaTypeAdapter(DoubleAdapter.class) 
    public Double maxDouble = Double.MAX_VALUE; 

    @XmlJavaTypeAdapter(DoubleAdapter.class) 
    public Double aDouble = 123d; 

} 

Code Demo

package example; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Root.class); 
     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(new Root(), System.out); 
    } 

} 

MISE À JOUR

suggestion de StaxMan est un bon. Si vous spécifiez l'annotation au niveau du package suivant, vous pouvez éviter la nécessité d'annoter individuellement toutes les propriétés Double

package-info.java

@XmlJavaTypeAdapters({ 
    @XmlJavaTypeAdapter(type=Double.class, value=DoubleAdapter.class) 
}) 
package example; 

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; 
+0

Je regardais cette approche.Le problème est qu'il serait problématique de marquer tous les champs doubles dans la classe héritée. Je cherchais un "hook" global où l'on pourrait spécifier ou mettre exactement le type d'adaptateur de type que vous listez ci-dessus. C'est-à-dire quelque chose qui dit "pour chaque champ double dans cette classe, utilisez ce XmlAdapter". –

+2

Vous pouvez également ajouter des annotations @XmlAdapter pour les paquets (package-info.java peut contenir des annotations!) - vérifiez les docs java. Cela pourrait rendre cette approche possible – StaxMan

+0

J'ai mis à jour ma réponse pour inclure la suggestion de StaxMan. –

0

Écrire un getter qui retourne nulle, au lieu de Double.MAX_VALUE ? (si le type est 'double', vous devez d'abord le changer en 'Double', pour autoriser les valeurs nulles). Puisque JAXB ignore par défaut l'écriture des valeurs nulles, cela devrait atteindre ce que vous essayez de faire. Cela suppose que vous pouvez modifier la classe héritée en question.

+1

Merci pour votre suggestion. Malheureusement, la classe héritée ne peut pas être facilement modifiée (et il y a un "million" de champs doubles publics qui doivent être enveloppés). Je cherchais une solution plus facile ... –

Questions connexes