问题描述
我有一个示例课:
class Zoo {
public Collection<? extends Animal> animals;
}
使用MOXy序列化时,我得到:
When serialized with MOXy, I am getting:
{
"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 is it using array indicators "[]", while bird, cat, and dog are not arrays?Second, is there a way to get rid of "bird", "cat", and "dog"?
换句话说,我试图到达:
In other words, I am trying to get to:
{
{
"name": "bird-1",
"wingSpan": "6 feets",
"preferredFood": "food-1"
}
,
{
"name": "cat-1",
"favoriteToy": "toy-1"
}
,
{
"name": "dog-1",
"breed": "bread-1",
"leashColor": "black"
}
}
谢谢,Behzad
Thanks,Behzad
推荐答案
问题1
要获取此JSON表示,您已使用@XmlElementRef
注释映射了模型,该注释告诉JAXB将@XmlRootElement
注释的值用作继承指示符.使用MOXy的JSON绑定,这些就成为了关键.由于不允许重复键,因此我们将这些键的值设为JSON数组.
To get this JSON representation you have mapped your model with the @XmlElementRef
annotation which tells JAXB to use the value of the @XmlRootElement
annotation as the inheritance indicator. With MOXy's JSON binding these become keys. We make the value of these keys JSON arrays since keys are not allowed to repeat.
动物园
在模型中,您的animals
字段/属性上具有@XmlElementRef
注释.
In your model you have the @XmlElementRef
annotation on your animals
field/property.
import java.util.Collection;
import javax.xml.bind.annotation.XmlElementRef;
class Zoo {
@XmlElementRef
public Collection<? extends Animal> animals;
}
动物
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Bird.class, Cat.class, Dog.class})
public abstract class Animal {
private String name;
}
鸟
在每个子类上,都有一个@XmlRootElement
批注.
On each of your subclasses you have an @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"
} ]
}
更多信息
问题#2
您将需要某种继承指示器来表示各个子类.
You are going to need some sort of inheritance indicator to represent the various subclasses.
选项#1-@XmlDescriminatorNode
/@XmlDescriminatorValue
在这里,我使用MOXy的@XmlDescriminatorNode
/@XmlDescriminatorValue
注释.
Here I do this using MOXy's @XmlDescriminatorNode
/@XmlDescriminatorValue
annotations.
动物园
import java.util.Collection;
class Zoo {
public Collection<? extends Animal> animals;
}
动物
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Bird.class, Cat.class, Dog.class})
@XmlDiscriminatorNode("@type")
public abstract class Animal {
private String name;
}
鸟
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",
"wingSpan" : "6 feets",
"preferredFood" : "food-1"
}, {
"type" : "cat",
"name" : "cat-1",
"favoriteToy" : "toy-1"
}, {
"type" : "dog",
"name" : "dog-1",
"breed" : "bread-1",
"leashColor" : "black"
} ]
}
更多信息
选项#2-@XmlClassExtractor
ClassExtractor(动物提取器)
您可以编写一些代码,这些代码将根据JSON内容确定适当的子类.
You can write some code that will determine the appropriate subclass based on the 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;
}
}
}
动物
@XmlClassExtractor
批注用于指定ClassExtractor
.
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlClassExtractor;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Bird.class, Cat.class, Dog.class})
@XmlClassExtractor(AnimalExtractor.class)
public abstract class Animal {
private String name;
}
鸟
由于MOXy是如何处理@XmlElement
和@XmlAttribute
批注的,因此您想要提供给ClassExtractor
的任何数据都需要使用@XmlAttribute
进行注释.
Due to how MOXy processes the @XmlElement
and @XmlAttribute
annotations, any of the data you want to be made available to the ClassExtractor
will need 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"
} ]
}
更多信息
演示代码
以下演示代码可与上述两个映射一起使用.
The following demo code can be used with both of the mappings described above.
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);
}
}
这篇关于EclipseLink MOXy JSON序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!