2013-06-28 16 views
10

devo visualizzare il valore null come elemento vuoto in jaxb. Sto usando l'implementazione moxy di jaxb. Ho trovato questa opzionerappresentare un valore nullo come elemento vuoto in XML jaxb

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

Esiste prolungamento simile che può essere applicata a livello di classe (per tutti gli elementi in esso definite)

risposta

16

Consiglio vivamente rappresenta null con l'assenza del nodo o con l'attributo xsi:nil="true". Questo funziona meglio con la convalida dello schema (cioè <age/> o <age></age> non è un elemento valido di tipo xsd:int Tuttavia, se non qui si può è come è possibile realizzare il vostro caso d'uso:.

STANDARD JAXB COMPORTAMENTO

Utilizzando le API standard è possibile controllare se nulla viene rappresentato come un nodo assente o con xsi:nil="true" con il @XmlElement nota (vedi: 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; 

} 

riportano di seguito le outpu XML. t se i valori di entrambi i campi sono nulli.

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

Moxy - sovrascrivere questa COMPORTAMENTO PER RAMO

moxy non fornisce un'annotazione per specificare la politica null per tutti gli immobili in una classe. Tuttavia è possibile sfruttare un DescriptorCustomizer tramite il @XmlCustomizer annotazione e modificare i metadati di mapping Moxy nativo per ottenere la stessa cosa.

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); 
      } 
     } 
    } 

} 

domain model (Indirizzo)

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; 

} 

uscita

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

Moxy - sovrascrivere questa COMPORTAMENTO PER TUTTE LE CATEGORIE

Se invece si desidera ignorare la gestione nullo per tutte le classi mappate Ti consiglio di utilizzare una SessionEventListener invece. Se preferisci, potresti anche utilizzare questo approccio per aggiornare i metadati per una singola classe.

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); 
       } 
      } 
     } 
    } 

} 

Codice Demo

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); 
    } 

} 

uscita

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

Una soluzione "cattiva pratica", se si hanno solo i campi String nella classe è quello di ignorare il setter per l'elemento in questo modo:

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()! 
    } 
    } 
} 

Questo non funzionerà con altri tipi come la data o il numero ! Ma a volte String è abbastanza.

@Blaise La risposta di Doughan sembra molto migliore a lungo termine se è possibile affrontarla. :)

Problemi correlati