web-dev-qa-db-fra.com

JAXB Marshalling avec des champs nuls

C'est une demande assez simple, mais je n'ai tout simplement pas trouvé le moyen de le faire.

En gros, j'essaie de définir un rôle dans JAXB, qui indique que chaque fois qu'un champ null est rencontré, au lieu de l'ignorer dans la sortie, définissez-le sur une valeur vide. Donc pour la classe:

@XMLRootElement
Class Foo {
   Integer num;
   Date date;
….
}

Lorsque cela a été structuré dans le fichier XML si le champ de date est null, ma sortie ne contient pas cet élément. Ce que je veux faire, c'est inclure tous les champs dans la sortie; et si elles sont nulles, remplacez-les par - disons un blanc. Donc, le résultat devrait être:

<foo>
  <num>123</num>
  <date></date>
</foo>

Merci,

Jalpesh.

47
Jalpesh

Merci les gars pour vos réponses.

Chris Dail - J'ai essayé votre approche et elle n'a pas vraiment fait ce que je voulais. JAXB ignorait toujours mes valeurs NULL, malgré la définition d'une valeur par défaut pour mes champs.

Je suis tombé sur la réponse après que quelqu'un des forums de Jersey m'a indiqué la section documentation 2.2.12.8 Aucune valeur .

Fondamentalement, tout ce que je devais faire était d’ajouter ce qui suit dans mes champs:

@XmlElement(nillable = true) 

Une fois que j’aurais ajouté cela, JAXB afficherait ces champs lorsqu’ils seraient classés en XML comme ceci:

...
<num>5</num>
<date xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
....
39
Jalpesh

Mais mais mais ... une chaîne vide n'est pas une représentation lexicale valide pour une date, vous ne pouvez donc pas le faire. Par exemple, si vous avez généré un document XML avec une valeur vide pour un champ de date, il ne sera pas validé correctement.

En d'autres termes, si votre élément date a une minOccurs de 1 ou plus et non nillable, alors vous devez absolument avoir (une ou plusieurs) dates, qui ne peuvent pas être nulles (ou des blancs, ou d'autres non-valeurs).

4

Dans MOXy, vous pouvez spécifier comment jsonProvider doit effectuer son travail pour JAXB.

Donc, lorsque vous utilisez JAX-RS, ajoutez le code suivant dans votre classe dérivé de Application

J'ai utilisé ce code sur Tomcat 7 avec de bons résultats. (eclipselink 2.4.1)

@ApplicationPath("/rest")
public class RestApplication extends Application
{

  ...

 public Set< Object> getSingletons()
  {

    HashSet<Object> set = new HashSet<Object>(1);
    set.add( newMoxyJsonProvider());

    return set;
  }


 public static MOXyJsonProvider newMoxyJsonProvider()
  {

    MOXyJsonProvider result = new MOXyJsonProvider();

    //result.setAttributePrefix("@");
    result.setFormattedOutput( false);
    result.setIncludeRoot( false);
    result.setMarshalEmptyCollections( true);
    //result.setValueWrapper("$");

    return result;
  }

Cependant, sur Glassfish 3.1.2 et WAS 8.5, newMoxyJsonProvider () n'est pas nécessaire, mais le fournisseur JAXB est alors configuré par le serveur. Dans le cas de Glassfish, fourni avec MOXy, j’ai été témoin des mêmes problèmes avec les valeurs nulles. N'a pas encore vérifié, mais la réponse est de configurer JAXB au niveau du serveur d'applications, si possible.

1
Jan Serneels

Comme indiqué dans l’autre réponse, elle est invalide car ce n’est pas une date valide. J'ai eu un problème similaire où je voulais gérer (même que) spécialement. Étant donné que vous ne pouvez pas utiliser la valeur null, vous pouvez utiliser le mécanisme de valeur par défaut dans JAXB. Ce qui suit sera la valeur par défaut si aucune n'est spécifiée. Vous pouvez via le code détecter cette date spéciale et gérer ce cas d'exception.

@XmlElement(defaultValue="1970-01-01T00:00:00.0-00:00")

Il est donc possible de détecter et de vider la date, mais vous ne pouvez pas utiliser null pour le faire.

1
Chris Dail

Essaye ça:

marshal.setListener(new MarshallerListener());

avec

public class MarshallerListener extends Marshaller.Listener {

    public static final String BLANK_CHAR = "";

    @Override
    public void beforeMarshal(Object source) {
        super.beforeMarshal(source);
        Field[] fields = source.getClass().getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            try {
                if (f.getType() == String.class && f.get(source) == null) {
                    f.set(source, BLANK_CHAR);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
0
xudd