Java – eclipse link Moxy JSON serialization

I have an example class:

class Zoo {
    public Collection<? extends Animal> animals;
}

When serializing with Moxy, I get:

{
    "bird": [
        {
            "name": "bird-1","wingSpan": "6 feets","preferredFood": "food-1"
        }
    ],"cat": [
        {
            "name": "cat-1","favoriteToy": "toy-1"
        }
    ],"dog": [
        {
            "name": "dog-1","breed": "bread-1","leashColor": "black"
        }
    ]
}

Why use the array indicator "[]", while birds, cats and dogs are not arrays? Second, is there any way to get rid of "birds", "Cats" and "dogs"?

In other words, I try to:

{
        {
            "name": "bird-1","preferredFood": "food-1"
        },{
            "name": "cat-1","favoriteToy": "toy-1"
        },{
            "name": "dog-1","leashColor": "black"
        }
}

Thank you, Behzad

Solution

Question #1

To get this JSON representation, you have mapped the model to the @ xmlelementref annotation, which tells JAXB to use the value of the @ xmlrootelement annotation as the inheritance indicator Using the JSON binding of Moxy becomes the key We make the values of these key JSON values as keys are not allowed to be repeated

zoo

In your model, your animal field / attribute has @ xmlelementref annotation

import java.util.Collection;
import javax.xml.bind.annotation.XmlElementRef;

class Zoo {
    @XmlElementRef
    public Collection<? extends Animal> animals;
}

animal

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Bird.class,Cat.class,Dog.class})
public abstract class Animal {

    private String name;

}

bird

On each subclass, there is a @ xmlrootelement annotation

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Bird extends Animal {

    private String wingSpan;
    private String preferredFood;

}

input. JSON / output

{
   "bird" : [ {
      "name" : "bird-1","wingSpan" : "6 feets","preferredFood" : "food-1"
   } ],"cat" : [ {
      "name" : "cat-1","favoriteToy" : "toy-1"
   } ],"dog" : [ {
      "name" : "dog-1","breed" : "bread-1","leashColor" : "black"
   } ]
}

Learn more

> http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html

Question #2:

You will need some kind of inheritance metric to represent various subclasses

Options #1 – @ xmldescriptornode / @ xmldescriptorvalue

Here I use @ xmldescriptornode / @ xmldescriptorvalue annotation of Moxy

zoo

import java.util.Collection;

class Zoo {
    public Collection<? extends Animal> animals;
}

animal

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Bird.class,Dog.class})
@XmlDiscriminatorNode("@type")
public abstract class Animal {

    private String name;

}

bird

import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;

@XmlDiscriminatorValue("bird")
public class Bird extends Animal {

    private String wingSpan;
    private String preferredFood;

}

input. JSON / output

{
   "animals" : [ {
      "type" : "bird","name" : "bird-1","preferredFood" : "food-1"
   },{
      "type" : "cat","name" : "cat-1","favoriteToy" : "toy-1"
   },{
      "type" : "dog","name" : "dog-1","leashColor" : "black"
   } ]
}

Learn more

> http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-moxy-extension.html

Options #2 – @ xmlclassextractor

ClassExtractor(AnimalExtractor)

You can write some code to determine the appropriate subclass based on JSON content

import org.eclipse.persistence.descriptors.ClassExtractor;
import org.eclipse.persistence.sessions.*;

public class AnimalExtractor extends ClassExtractor {

    @Override
    public Class extractClassFromRow(Record record,Session session) {
        if(null != record.get("@wingSpan") || null != record.get("@preferredFood")) {
            return Bird.class;
        } else if(null != record.get("@favoriteToy")) {
            return Cat.class;
        } else {
            return Dog.class;
        }
    }

}

animal

@The xmlclassextractor annotation is used to specify classextractor

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlClassExtractor;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Bird.class,Dog.class})
@XmlClassExtractor(AnimalExtractor.class)
public abstract class Animal {

    private String name;

}

bird

Because of how Moxy handles @ xmlelement and @ xmlattribute annotations, any data you want to make available to classextractor needs to be annotated with @ xmlattribute

import javax.xml.bind.annotation.XmlAttribute;

public class Bird extends Animal {

    @XmlAttribute
    private String wingSpan;

    @XmlAttribute
    private String preferredFood;

}

input. JSON / output

{
   "animals" : [ {
      "wingSpan" : "6 feets","preferredFood" : "food-1","name" : "bird-1"
   },{
      "favoriteToy" : "toy-1","name" : "cat-1"
   },{
      "breed" : "bread-1","leashColor" : "black","name" : "dog-1"
   } ]
}

Learn more

> http://blog.bdoughan.com/2012/02/jaxb-and-inheritance-eclipselink-moxy.html

Demo code

The following demonstration code can be used for the above two mappings

import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String,Object> properties = new HashMap<String,Object>();
        properties.put(JAXBContextProperties.MEDIA_TYPE,"application/json");
        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT,false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Zoo.class},properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StreamSource json = new StreamSource("src/forum14210676/input.json");
        Zoo zoo = unmarshaller.unmarshal(json,Zoo.class).getValue();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
        marshaller.marshal(zoo,System.out);
    }

}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>