2013-06-28 33 views
10

Tôi cần hiển thị giá trị null làm phần tử trống trong jaxb. Tôi đang sử dụng moxy thực hiện của jaxb. tôi thấy tùy chọn nàyBiểu thị giá trị null dưới dạng phần tử trống trong xml jaxb

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

Có bất kỳ phần mở rộng tương tự có thể được áp dụng ở cấp lớp (cho tất cả các yếu tố quy định tại nó)

Trả lời

16

Tôi rất muốn giới thiệu đại diện null với một trong hai sự vắng mặt của nút hoặc với thuộc tính xsi:nil="true". Sẽ hiệu quả nhất với xác nhận schema (tức <age/> hoặc <age></age> không phải là một yếu tố có giá trị của loại xsd:int Tuy nhiên nếu bạn không ở đây có thể là cách bạn có thể thực hiện trường hợp sử dụng của bạn:.

TIÊU CHUẨN JAXB HÀNH VI

Sử dụng API tiêu chuẩn mà bạn có thể kiểm soát xem null được biểu diễn dưới dạng một nút vắng mặt hoặc với xsi:nil="true" với @XmlElement chú thích (xem: 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; 

} 

Dưới đây là outpu XML. t nếu giá trị của cả hai trường là null.

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

MOXY - trọng HÀNH VI NÀY CHO MỖI LỚP

MOXY không cung cấp một chú thích để xác định chính sách null cho tất cả các tài sản trên một lớp. Tuy nhiên, bạn có thể tận dụng một số DescriptorCustomizer qua chú thích @XmlCustomizer và tinh chỉnh siêu dữ liệu bản đồ MOXy gốc để thực hiện điều tương tự.

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 (Địa chỉ)

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; 

} 

Output

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

MOXY - trọng HÀNH VI NÀY CHO TẤT CẢ CÁC LỚP HỌC

Nếu thay vào đó bạn muốn ghi đè lên xử lý null cho tất cả các lớp ánh xạ Tôi muốn giới thiệu cách sử dụng một SessionEventListener để thay thế. Nếu bạn thích, bạn cũng có thể sử dụng phương pháp này để cập nhật siêu dữ liệu cho một lớp duy nhất.

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 Mã

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

} 

Output

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

A "thực hành xấu" workaround nếu bạn chỉ có lĩnh vực String trong lớp là để ghi đè lên các setter cho các phần tử như thế này:

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

này wont work với các loại khác như ngày tháng hoặc số ! Nhưng đôi khi String là đủ.

@Blaise Câu trả lời của Doughan có vẻ tốt hơn trong dài hạn nếu bạn có thể giải quyết. :)

Các vấn đề liên quan