Search code examples
javajaxbjax-rsjaxb2

how to map a bean structure to a different schema with jax-rs


I have this bean

@XmlRootElement
class Test {
   boolean someValue;
   List<Field> fields;
}

I would like to serialize it as

<fields>
   <field>
       <name>someValue</name>
       <value>...</value>
   </field>
</fields>
<fields>
   <field>
       <name>otherValue</name>
       <value>...</value>
   </field>
</fields>

(or as json)

How should I do that, preferrably using jaxb annotations?

I'm using jersey, but the answer doens't have to be specific to it.


Solution

  • How about the following?

    Using EclipseLink JAXB (MOXy) you could do the following. Note: I'm the MOXy tech lead.

    Test

    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.bind.Unmarshaller;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlType;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    import org.eclipse.persistence.oxm.annotations.XmlPath;
    
    @XmlRootElement
    @XmlType(propOrder={"someValue", "fields"})
    @XmlAccessorType(XmlAccessType.FIELD)
    class Test {
    
        @XmlJavaTypeAdapter(SomeValueAdapter.class)
        @XmlPath("fields[1]")
        boolean someValue;
    
        @XmlJavaTypeAdapter(FieldsAdapter.class)
        List<Field> fields = new ArrayList<Field>();
    
        public Boolean isSomeValue() {
            return someValue;
        }
    
        public void setSomeValue(boolean someValue) {
            this.someValue = someValue;
        }
    
        public List<Field> getFields() {
            return fields;
        }
    
        public void setFields(List<Field> fields) {
            this.fields = fields;
        }
    
        public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
            for(Field field : fields) {
                if("someValue".equals(field.getName())) {
                    someValue = Boolean.valueOf(field.getValue());
                    fields.remove(field);
                }
            }
        }
    
    }
    

    Field

    public class Field {
    
        private String name;
        private String value;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
    }
    

    SomeValueAdapter

    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class SomeValueAdapter extends XmlAdapter<AdaptedField, Boolean> {
    
        @Override
        public Boolean unmarshal(AdaptedField v) throws Exception {
            String value = v.getField().getValue();
            return Boolean.valueOf(value);
        }
    
        @Override
        public AdaptedField marshal(Boolean v) throws Exception {
            AdaptedField adaptedField = new AdaptedField();
            Field field = new Field();
            field.setName("someValue");
            field.setValue(String.valueOf(v));
            adaptedField.setField(field);
            return adaptedField;
        }
    
    }
    

    FieldsAdapter

    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class FieldsAdapter extends XmlAdapter<AdaptedField, Field> {
    
        @Override
        public Field unmarshal(AdaptedField v) throws Exception {
            return v.getField();
        }
    
        @Override
        public AdaptedField marshal(Field v) throws Exception {
            AdaptedField adaptedField = new AdaptedField();
            adaptedField.setField(v);
            return adaptedField;
        }
    
    }
    

    AdaptedField

    public class AdaptedField {
    
        private Field field;
    
        public Field getField() {
            return field;
        }
    
        public void setField(Field field) {
            this.field = field;
        }
    
    }
    

    Demo

    import java.io.File;

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Test.class);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            Test test = (Test) unmarshaller.unmarshal(new File("input.xml"));
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(test, System.out);
        }
    
    }
    

    input.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <test>
       <fields>
          <field>
             <name>someValue</name>
             <value>true</value>
          </field>
       </fields>
       <fields>
          <field>
             <name>otherValue</name>
             <value>1</value>
          </field>
       </fields>
       <fields>
          <field>
             <name>anotherValue</name>
             <value>2</value>
          </field>
       </fields>
    </test>
    

    For More Information