是否有可能隐藏“@type”?使用 EclipseLink MOXy (JAXB) 将子类编组为 JSON 时的条目?

发布于 2024-11-16 08:48:44 字数 1288 浏览 4 评论 0原文

我即将开发一个基于 JAX-RS 的 RESTful Web 服务,并使用 MOXy (JAXB) 来自动生成 Web 服务的 JSON 响应。

一切都很酷,但由于 Web 服务将是基于 JavaScript 的 Web 应用程序的后端,因此可以公开访问,我不想公开某些详细信息,例如类名等。

但是,我已经意识到在某些条件下,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"

我的回复?

I'm about to develop a JAX-RS based RESTful web service and I use MOXy (JAXB) in order to automatically generate my web service's JSON responses.

Everything is cool, but due to the fact that the web service will be the back-end of a JavaScript-based web application and therefore publicly accessible I don't want to expose certain details like class names, etc.

But, I've realized that under certain conditions MOXy embeds a "@type" entry into the marshalled string and this entry is followed by the class name of the object that has just been marshalled.

In particular, I've realized that MOXy behaves in this way when marshalling instances of extended classes.

Assume the following super class "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;
}
}

And this specialized (extended) class "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;
}
}

So, the MyBasicResponse object's marshalled string is

{"msg":"A Message."}

(That's okay!)

But, the MySpecialResponse object's marshalled string is like

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

Is there a way to strip the

"@type":"MySpecialResponse"

out of my response?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

划一舟意中人 2024-11-23 08:48:44

您可以将对象包装在 JAXBElement 实例中,指定要编组的子类以消除类型键。下面是一个完整的例子。

Java 模型

与问题相同,但添加了以下 package-info 类来指定字段访问以匹配这些类

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

import javax.xml.bind.annotation.*;

演示代码

Demo

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);
    }

}

Output

我们看到,当对象被编组时,type 键被编组(对应于 XML 表示中的 xsi:type 属性),因为对于 MOXy 而言,这是必要的来区分MyBasicResponseMySpecialResponse。当我们将对象包装在 JAXBElement 实例中并限定类型 MOXy 时,不需要添加 type 键。

{
   "type" : "mySpecialResponse"
}
{
}

欲了解更多信息

You can wrap your object in an instance of JAXBElement specifying the subclass being marshalled to get rid of the type key. Below is a full example.

Java Model

Same as from the question, but with the following package-info class added to specifying the field access to match those classes

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

import javax.xml.bind.annotation.*;

Demo Code

Demo

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);
    }

}

Output

We see that when the object was marshalled an type key was marshalled (corresponding to the xsi:type attribute in the XML representation), because as MOXy is concerned it was necessary to distinguish between MyBasicResponse and MySpecialResponse. When we wrapped the object in an instance of JAXBElement and qualified the type MOXy didn't need to add the type key.

{
   "type" : "mySpecialResponse"
}
{
}

For More Information

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文