it-swarm.com.de

Stellt einen Nullwert als leeres Element in XML Jaxb dar

Ich muss Nullwert als leeres Element in Jaxb anzeigen. Ich verwende die moxy-Implementierung von jaxb. Ich habe diese Option gefunden

@XmlNullPolicy(emptyNodeRepresentsNull = true, nullRepresentationForXml = XmlMarshalNullRepresentation.EMPTY_NODE)

Gibt es eine ähnliche Erweiterung, die auf Klassenebene angewendet werden kann (für alle darin definierten Elemente)

11
Anand B

Ich würde dringend empfehlen, null mit dem Fehlen des Knotens oder mit dem xsi:nil="true"-Attribut darzustellen. Dies funktioniert am besten mit der Schemaüberprüfung (d. H. <age/> oder <age></age> ist kein gültiges Element vom Typ xsd:int. Wenn Sie dies jedoch nicht tun können, können Sie Ihren Anwendungsfall wie folgt ausführen:

STANDARD JAXB VERHALTEN

Mit den Standard-APIs können Sie steuern, ob Null als abwesender Knoten oder mit xsi:nil="true" mit der Annotation @XmlElement dargestellt wird (siehe: http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling -null.html ).

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Address {

    private String street;

    @XmlElement(nillable=true)
    private String city;

}

Unten ist die XML-Ausgabe, wenn die Werte beider Felder NULL sind.

<?xml version="1.0" encoding="UTF-8"?>
<address>
   <city xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</address>

MOXy - VERHINDERN DIESES VERHALTENS PRO KLASSE

MOXy enthält keine Anmerkung, um die Nullrichtlinie für alle Eigenschaften einer Klasse anzugeben. Sie können jedoch eine DescriptorCustomizer über die @XmlCustomizer-Annotation nutzen und die nativen MOXy-Mapping-Metadaten anpassen, um dasselbe zu erreichen.

DescriptorCustomizer (AddressCustomizer)}

import org.Eclipse.persistence.config.DescriptorCustomizer;
import org.Eclipse.persistence.descriptors.ClassDescriptor;
import org.Eclipse.persistence.mappings.DatabaseMapping;
import org.Eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.Eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType;

public class AddressCustomizer implements DescriptorCustomizer {

    @Override
    public void customize(ClassDescriptor descriptor) throws Exception {
        for(DatabaseMapping mapping : descriptor.getMappings()) {
            if(mapping.isAbstractDirectMapping()) {
                XMLDirectMapping xmlDirectMapping = (XMLDirectMapping) mapping;
                xmlDirectMapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.EMPTY_NODE);
                xmlDirectMapping.getNullPolicy().setNullRepresentedByEmptyNode(true);
            }
        }
    }

}

DomainModel (Adresse)

import javax.xml.bind.annotation.*;
import org.Eclipse.persistence.oxm.annotations.XmlCustomizer;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlCustomizer(AddressCustomizer.class)
public class Address {

    private String street;

    @XmlElement(nillable=true)
    private String city;

}

Ausgabe

<?xml version="1.0" encoding="UTF-8"?>
<address>
   <street/>
   <city/>
</address>

MOXy - DAS VERHALTEN DIESES VERHALTENS FÜR ALLE KLASSEN

Wenn Sie stattdessen die Nullbehandlung für alle zugeordneten Klassen überschreiben möchten, würde ich empfehlen, stattdessen eine SessionEventListener zu verwenden. Wenn Sie möchten, können Sie diese Methode auch verwenden, um die Metadaten für eine einzelne Klasse zu aktualisieren.

SessionEventListener (NullPolicySessionEventListener)}

import org.Eclipse.persistence.descriptors.ClassDescriptor;
import org.Eclipse.persistence.mappings.DatabaseMapping;
import org.Eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.Eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType;
import org.Eclipse.persistence.sessions.*;

public class NullPolicySessionEventListener extends SessionEventAdapter {

    @Override
    public void preLogin(SessionEvent event) {
        Project project = event.getSession().getProject();
        for(ClassDescriptor descriptor : project.getOrderedDescriptors()) {
            for(DatabaseMapping mapping : descriptor.getMappings()) {
                if(mapping.isAbstractDirectMapping()) {
                    XMLDirectMapping xmlDirectMapping = (XMLDirectMapping) mapping;
                    xmlDirectMapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.EMPTY_NODE);
                    xmlDirectMapping.getNullPolicy().setNullRepresentedByEmptyNode(true);
                }
            }
        }
     }

}

Demo Code

import Java.util.*;
import javax.xml.bind.*;
import org.Eclipse.persistence.jaxb.JAXBContextProperties;
import org.Eclipse.persistence.sessions.SessionEventListener;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        SessionEventListener sessionEventListener = new NullPolicySessionEventListener();
        properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, sessionEventListener);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Address.class}, properties);

        Address address = new Address();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(address, System.out);
    }

}

Ausgabe

<?xml version="1.0" encoding="UTF-8"?>
<address>
   <street/>
   <city/>
</address>
18
Blaise Doughan

Wenn Sie nur String-Felder in der Klasse haben, können Sie den Setter für das Element wie folgt überschreiben:

public class Address {

  private String street;

  @XmlElement(name = "street")
  public void setStreet(String street){
    this.street = street;
    if (this.street == null){
      this.street = ""; // Not NULL, empty string like new String()!
    }
  }
}

Dies funktioniert nicht mit anderen Typen wie Datum oder Nummer! Aber manchmal ist String genug.

@ Blaise Doughans Antwort scheint auf lange Sicht viel besser zu sein, wenn Sie damit umgehen können. :)

0
Laszlo Lugosi