One domain model, multiple json views

前端 未结 1 1963
攒了一身酷
攒了一身酷 2021-02-09 07:47

We have a set of domain classes which are serialized to json via jackson using jersey services. We are currently annotating the classes with JAXB (although we\'re not tied to th

相关标签:
1条回答
  • 2021-02-09 08:32

    Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

    MOXy offers JSON-binding based on JAXB annotations as well as an external binding document that allows you to apply alternate mappings to a domain model. I will demonstrate below with an example.

    Metadata as JAXB Annotations

    Below is a simple Java model mapping with the standard JAXB annotations.

    package forum10761762;
    
    import javax.xml.bind.annotation.*;
    
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Customer {
    
        int id;
    
        @XmlElement(name="first-name")
        String firstName;
    
        @XmlElement(name="last-name")
        String lastName;
    
    }
    

    Alternate Metadata #1 (alternate1.xml)

    Here we will use the XML mapping document to unmap a couple of fields by making them @XmlTransient.

    <?xml version="1.0"?>
    <xml-bindings
        xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
        package-name="forum10761762">
        <java-types>
            <java-type name="Customer">
                <java-attributes>
                    <xml-transient java-attribute="id"/>
                    <xml-transient java-attribute="firstName"/>
                 </java-attributes>
            </java-type>
        </java-types>
    </xml-bindings>
    

    Alternate Metadata #2 (alternate2.xml)

    Here we will map the Java model to a different JSON structure using MOXy's path based mapping extension.

    <?xml version="1.0"?>
    <xml-bindings
        xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
        package-name="forum10761762">
        <java-types>
            <java-type name="Customer">
                <java-attributes>
                    <xml-element java-attribute="firstName" xml-path="personalInfo/firstName/text()"/>
                    <xml-element java-attribute="lastName" xml-path="personalInfo/lastName/text()"/>
                 </java-attributes>
            </java-type>
        </java-types>
    </xml-bindings>
    

    Demo Code

    package forum10761762;
    
    import java.util.*;
    import javax.xml.bind.*;
    import org.eclipse.persistence.jaxb.JAXBContextProperties;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            Customer customer = new Customer();
            customer.id = 123;
            customer.firstName = "Jane";
            customer.lastName = "Doe";
    
            Map<String, Object> properties = new HashMap<String, Object>();
            properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
            properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
    
            // Output #1
            JAXBContext jc1 = JAXBContext.newInstance(new Class[] {Customer.class}, properties);
            marshal(jc1, customer);
    
            // Output #2
            properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum10761762/alternate1.xml");
            JAXBContext jc2 = JAXBContext.newInstance(new Class[] {Customer.class}, properties);
            marshal (jc2, customer);
    
            // Output #2
            properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum10761762/alternate2.xml");
            JAXBContext jc3 = JAXBContext.newInstance(new Class[] {Customer.class}, properties);
            marshal(jc3, customer);
        }
    
        private static void marshal(JAXBContext jc, Object object) throws Exception {
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(object, System.out);
            System.out.println();
        }
    
    }
    

    Output

    Below is the output from running the demo code. Note from the same object model 3 different JSON documents were produced.

    {
       "id" : 123,
       "first-name" : "Jane",
       "last-name" : "Doe"
    }
    {
       "last-name" : "Doe"
    }
    {
       "id" : 123,
       "personalInfo" : {
          "firstName" : "Jane",
          "lastName" : "Doe"
       }
    }
    

    For More Information (from my blog)

    • JSON Binding with EclipseLink MOXy - Twitter Example
    • MOXy as Your JAX-RS JSON Provider - MOXyJsonProvider
    • MOXy's XML Metadata in a JAX-RS Service
    • Specifying EclipseLink MOXy as Your JAXB Provider
    0 讨论(0)
提交回复
热议问题