EclipseLink MOXy JSON序列化 [英] EclipseLink MOXy JSON Serialization

查看:145
本文介绍了EclipseLink MOXy JSON序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个示例课:

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

为什么使用数组指示符"[]",而鸟,猫和狗是 不是数组?

Why is it using array indicators "[]", while bird, cat, and dog are not arrays?

要获取此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

第二,有没有办法摆脱鸟",猫"和狗"?

Second, is there a way to get rid of "bird", "cat", and "dog"?

您将需要某种继承指示器来表示各个子类.

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序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆