Java/JAXB: Unmarshall Xml to specific subclass based on an attribute

后端 未结 5 2113

Is it possible to use JAXB to unmarshall xml to a specific Java class based on an attribute of the xml?


  

        
5条回答
  •  Happy的楠姐
    2020-11-27 19:25

    JAXB is a spec, specific implementations will provide extension points to do things such as this. If you are using EclipseLink JAXB (MOXy) you could modify the Shape class as follows:

    import javax.xml.bind.annotation.XmlAttribute;
    import org.eclipse.persistence.oxm.annotations.XmlCustomizer;
    
    @XmlCustomizer(ShapeCustomizer.class)
    public abstract class Shape {
    
        int points;
    
        @XmlAttribute
        public int getPoints() {
            return points;
        }
    
        public void setPoints(int points) {
            this.points = points;
        }
    
    }
    

    Then using the MOXy @XMLCustomizer you could access the InheritancePolicy and change the class indicator field from "@xsi:type" to just "type":

    import org.eclipse.persistence.config.DescriptorCustomizer;
    import org.eclipse.persistence.descriptors.ClassDescriptor;
    
    public class ShapeCustomizer implements DescriptorCustomizer {
    
        @Override
        public void customize(ClassDescriptor descriptor) throws Exception {
            descriptor.getInheritancePolicy().setClassIndicatorFieldName("@type");
        }
    }
    

    You will need to ensure that you have a jaxb.properties file in with you model classes (Shape, Square, etc) with the following entry specifying the EclipseLink MOXy JAXB implementation:

    javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
    

    Below is the rest of the model classes:

    Shapes

    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class Shapes {
    
        private List shape = new ArrayList();;
    
        public List getShape() {
            return shape;
        }
    
        public void setShape(List shape) {
            this.shape = shape;
        }
    
    }
    

    Square

    import javax.xml.bind.annotation.XmlAttribute;
    
    public class Square extends Shape {
        private String squareSpecificAttribute;
    
        @XmlAttribute(name="square-specific-attribute")
        public String getSquareSpecificAttribute() {
            return squareSpecificAttribute;
        }
    
        public void setSquareSpecificAttribute(String s) {
            this.squareSpecificAttribute = s;
        }
    
    }
    

    Triangle

    import javax.xml.bind.annotation.XmlAttribute;
    
    public class Triangle extends Shape {
        private String triangleSpecificAttribute;
    
        @XmlAttribute(name="triangle-specific-attribute")
        public String getTriangleSpecificAttribute() {
            return triangleSpecificAttribute;
        }
    
        public void setTriangleSpecificAttribute(String t) {
            this.triangleSpecificAttribute = t;
        }
    
    }
    

    Below is a demo program to check that everything works:

    import java.io.StringReader;
    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 jaxbContext = JAXBContext.newInstance(Shapes.class, Triangle.class, Square.class);
    
            StringReader xml = new StringReader("43");
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            Shapes root = (Shapes) unmarshaller.unmarshal(xml);
    
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(root, System.out);
        }
    }
    

    I hope this helps.

    For more information on EclipseLink MOXy see:

    • http://www.eclipse.org/eclipselink/moxy.php

    EDIT

    In EclipseLink 2.2 we're making this easier to configure, check out the following article for more information:

    • http://bdoughan.blogspot.com/2010/11/jaxb-and-inheritance-moxy-extension.html

提交回复
热议问题