Jersey序列化继承属性两次

时间:2011-03-10 11:48:54

标签: java jaxb jersey jax-rs

我有一个没有任何注释的java bean。我有一个继承自这个bean的类,带有JAXB注释。

Jersey(JAX-RS)将第二个类序列化为JSON。继承的属性在JSON中出现两次:名称来自XmlElement注释,而“camel-case”名称为java-bean属性。这是一个代码,说明了这一点:

class MyBean {

   private Integer beanField;

   public Integer getBeanField() { return beanField; }

   public void setBeanField(Integer value) { this.beanField = value; }

}

@XmlRootElement
class AnnotatedBean extends MyBean {

  @Override
  @XmlElement(name="field")
  public Integer getBeanField() { return super.getBeanField(); }
}

}

序列化后,我得到下一个JSON:

{ 
   "field" : 5,
   "beanField" : 5
}

(虽然我希望它只包含一个名为field的字段。)

我调查了JAXB marshaller实现,发现它从给定类的所有超类中编组属性(这意味着在我的示例中不可能摆脱奇怪的beanField属性)。

但我仍然希望我能错过一些东西。有没有办法只序列化带注释的属性?

1 个答案:

答案 0 :(得分:4)

要仅获取带注释的属性,请使用XmlAccessType.NONE:

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
class AnnotatedBean extends MyBean {
    ...
}

使用外化元数据映射第三方类

您可以在EclipseLink JAXB(MOXy)中使用external metadata extension,我是技术主管。它允许您为第三方类提供元数据。对于此示例,元数据将如下所示:

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="third.party.package">
    <java-types>
        <java-type name="MyBean" xml-transient="true"/>
    </java-types>
</xml-bindings>

要使用MOXy,您需要使用以下条目在模型类中添加名为jaxb.properties的文件:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

以下文章提供了有关配置MOXy以使用Jersery的说明:

上下文解析器 - 利用元数据

您需要使用ContextResolver来获取JAXBContext以利用外部绑定文件。在实例化JAXBContext时,通过属性指定元数据:

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Produces;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.JAXBContextFactory;

@Provider
@Produces({"application/xml", "application/json"})
public class AnnotatedBeanContextResolver implements ContextResolver<JAXBContext> {

    private JAXBContext jaxbContext;

    public PurchaseOrderContextResolver() {
        try {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, new File("src/blog/bindingfile/binding.xml"));
        jaxbContext = JAXBContext.newInstance(new Class[] {AnnotatedBean.class}, properties);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

    public JAXBContext getContext(Class<?> clazz) {
        if(AnnotatedBean.class == clazz) {
            return jaxbContext;
        }
        return null;
    }

}