Есть ли возможность скрыть запись "@type" при маршалинге подклассов в JSON с помощью EclipseLink MOXy (JAXB)? - PullRequest
5 голосов
/ 21 июня 2011

Я собираюсь разработать веб-сервис RESTful на основе JAX-RS и использую MOXy (JAXB) для автоматической генерации ответов JSON моего веб-сервиса.

Все круто, но из-за того, что веб-сервис будет серверной частью веб-приложения на основе JavaScript и, следовательно, общедоступным, я не хочу раскрывать некоторые детали, такие как имена классов и т. Д. *

Но я понял, что при определенных условиях MOXy встраивает запись «@type» в маршаллированную строку, и за этой записью следует имя класса объекта, который только что был маршализован.

В частности, я понял, что MOXy ведет себя таким образом при сортировке экземпляров расширенных классов.

Предположим, что следующий суперкласс "MyBasicResponse"

@XmlRootElement(name="res")

public class MyBasicResponse {

@XmlElement
private String msg;

public MyBasicResponse() {
    // Just for conformity
}

public String getMsg() {
    return msg;
}

public void setMsg(String msg) {
    this.msg = msg;
}
}

А это специализированный (расширенный) класс "MySpecialResponse"

@XmlRootElement(name="res")

public class MySpecialResponse extends MyBasicResponse {

@XmlElement
private String moreInfo;

public MySpecialResponse() {
    // Just for conformity
}

public String getMoreInfo() {
    return moreInfo;
}

public void setMoreInfo(String moreInfo) {
    this.moreInfo = moreInfo;
}
}

Итак, маршаллированная строка объекта MyBasicResponse равна

{"msg":"A Message."}

(Это нормально!)

Но маршаллированная строка объекта MySpecialResponse имеет вид

{"@type":"MySpecialResponse","msg":"A Message.","moreInfo":"More Information."}

Есть ли способ раздеть

"@type":"MySpecialResponse"

из моего ответа?

1 Ответ

2 голосов
/ 21 июня 2011

Вы можете обернуть ваш объект в экземпляр JAXBElement, указав маршал для подкласса, чтобы избавиться от ключа типа. Ниже приведен полный пример.

Модель Java

То же, что и в вопросе, но со следующим классом package-info, добавленным для указания поля доступа для соответствия этим классам

@XmlAccessorType(XmlAccessType.FIELD)
package com.example.foo;

import javax.xml.bind.annotation.*;

Демо-код

Демо

import java.util.*;
import javax.xml.bind.*;
import javax.xml.namespace.QName;

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>(2);
        properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {MySpecialResponse.class}, properties);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        MySpecialResponse msr = new MySpecialResponse();
        marshaller.marshal(msr, System.out);

        JAXBElement<MySpecialResponse> jaxbElement = new JAXBElement(new QName(""), MySpecialResponse.class, msr);
        marshaller.marshal(jaxbElement, System.out);
    }

}

выход

Мы видим, что при маршалировании объекта маршалировался ключ type (соответствующий атрибуту xsi:type в XML-представлении), поскольку в отношении MOXy было необходимо различать MyBasicResponse и MySpecialResponse , Когда мы обернули объект в экземпляр JAXBElement и уточнили тип MOXy, не нужно было добавлять ключ type.

{
   "type" : "mySpecialResponse"
}
{
}

Для получения дополнительной информации

...