Can you change the default value of the nillable attribute in JAXB?

I'm refactoring some code to use JAXB and reflection to output the code to the client, it currently uses XMLWriter and manually creates tags every time.

The problem I am facing is that due to client-side restrictions, I need to have empty elements in XML for any null fields in the java class.

As long as I understand that this problem can be solved by adding nillable=true to each JAXB XmlElement annotation, this is not the most practical, since I have a lot of these annotations.

I was hoping to find a way to set nillable=true as a global attribute (or as the default). It would also facilitate the work of future colleagues, since they would not need to remember that each annotation should include the nillable attribute.

I did not find much other than a description of the default behavior. It seems surprising to me that in the past no one asked a similar question. From what I found, it doesn't seem to me that there is built-in support for the default setting. Is this something that can be solved with a custom JAXB implementation, or perhaps a third-party JAXB implementation?

+6
source share
1 answer

Note. I am EclipseLink JAXB (MOXy) and a member of the JAXB 2 group (JSR-222) .

I entered an extension request to add this behavior to EclipseLink JAXB (MOXy):

WORK AROUND

How it works, if all the displayed fields / String properties are mapped to XML elements, the following XmlAdapter approach may work for you:

Nullstringadapter

This XmlAdapter will march String instances as an object named AdaptedString . AdaptedString contains a String value, as well as a field mapped to the xsi:nil attribute. In the XmlAdapter we set the value of this field depending on whether the String value is zero.

 package forum8841221; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.*; public class NullStringAdapter extends XmlAdapter<NullStringAdapter.AdaptedString, String> { @Override public AdaptedString marshal(String v) throws Exception { AdaptedString adaptedString = new AdaptedString(); if(null == v) { adaptedString.nil = true; } adaptedString.value = v; return adaptedString; } @Override public String unmarshal(AdaptedString v) throws Exception { return v.value; } public static class AdaptedString { @XmlAttribute(namespace="http://www.w3.org/2001/XMLSchema-instance") public Boolean nil; @XmlValue @XmlJavaTypeAdapter(VoidStringAdapter.class) public String value; } public static class VoidStringAdapter extends XmlAdapter<String, String> { @Override public String marshal(String v) throws Exception { return v; } @Override public String unmarshal(String v) throws Exception { return v; } } } 

package info

We can register that we want this XmlAdapter applied to all displayed fields / String properties on this package by registering the XmlAdapter at the package level.

 @XmlJavaTypeAdapter(value=NullStringAdapter.class, type=String.class) @XmlSchema(xmlns={@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")}) package forum8841221; import javax.xml.bind.annotation.adapters.*; import javax.xml.bind.annotation.*; 

Root

The following is the domain class that I used for this example. It has several String properties, one of which is annotated using @XmlElement (nillable = true)

 package forum8841221; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Root { private String a; private String b; private String c; private String d; public String getA() { return a; } public void setA(String a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } public String getC() { return c; } public void setC(String c) { this.c = c; } @XmlElement(nillable=true) public String getD() { return d; } public void setD(String d) { this.d = d; } } 

Demo

 package forum8841221; 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); Root root = new Root(); root.setB("B"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } } 

Exit

 <?xml version="1.0" encoding="UTF-8"?> <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <a xsi:nil="true"/> <b>B</b> <c xsi:nil="true"/> <d xsi:nil="true"/> </root> 
+1
source

Source: https://habr.com/ru/post/905859/


All Articles