【问题标题】:JAXB annotated POJO for JSON serialization in Jersey returns String for every field type泽西岛中用于 JSON 序列化的 JAXB 注释 POJO 为每个字段类型返回字符串
【发布时间】:2012-10-08 19:39:37
【问题描述】:

我正在使用 Jersey 为服务器组件创建 Web 服务。不幸的是,我的 JSON 响应的格式存在问题,因为数据总是被格式化为字符串。

我有一个带有不同字段类型的简单 JAXB 注释 POJO:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class JaxbPojo {

    @XmlElement(name = "id_64")
    private Long id;

    @XmlElement(name = "desc")
    private String description;

    private Boolean active;

    // getters and setters
    ..
}

还有一个简单的资源,返回传入的对象:

@Path("/jaxb_pojo")
public class JaxbPojoResource {

    @POST
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces({ MediaType.APPLICATION_JSON })
    public JaxbPojo processBidRequest(JaxbPojo pojo) {
         return pojo;
    }

}

当使用以下 JSON 数据向资源发送请求时,该对象在资源方法中被正确填充。但是返回的 JSON 数据的字段类型总是格式化为字符串:

me@host:/tmp $ cat simple_jaxb_pojo 
{"id_64":99,"desc":"simple JAXB POJO","active":true}

me@host:/tmp $ curl -X POST -H "Content-Type: application/json" --data-binary @simple_jaxb_pojo http://localhost/srvr/rest/jaxb_pojo
{"id_64":"99","desc":"simple JAXB POJO","active":"true"}

所有使用的jar文件(jsr311-api-1.1.1.jar、jersey-core-1.6.jar、jersey-json-1.6.jar、jersey-server-1.6.jar)都直接包含在tomcat/lib中小路。 JAX-RS 库通过 Maven pom.xml 使用,范围为“提供”:

<dependency>
    <groupId>javax.ws.rs</groupId>
    <artifactId>jsr311-api</artifactId>
    <version>1.1.1</version>
    <scope>provided</scope>
</dependency>

我的 web.xml 看起来像这样:

<servlet>
    <servlet-name>RestServlet</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.rest.RestResourcesApplication</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

..

<servlet-mapping>
    <servlet-name>RestServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

我是否遗漏了什么,或者我可能必须以使用我的 POJO 类型的方式显式配置 Jackson。我对这个主题相当陌生,所以我发布了我所拥有的所有信息。我希望有人可以提供帮助。

【问题讨论】:

    标签: json jaxb jersey jackson jax-rs


    【解决方案1】:

    有趣的问题。我不确定为什么会发生这种情况,但请尝试添加:

        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
    

    到 web.xml 中的 Jersey servlet 定义。我认为 Jersey 需要它来生成 JSON,但是当我删除这个 init-param 时,我看到了你遇到的同样的问题。

    【讨论】:

    • 感谢您的回答。但是添加了这个我得到以下异常:严重:Java 类 ..JaxbPojo 和 Java 类型类 ..JaxbPojo 和 MIME 媒体类型应用程序/json 的消息正文阅读器未找到 18.10.2012 18:56:43 com。 sun.jersey.spi.container.ContainerRequest getEntity SEVERE:注册的与MIME媒体类型兼容的消息体阅读器为:application/json -> com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App com.sun .jersey.json.impl.provider.entity.JSONRootElementProvider$App com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$
    • 您确定 jersey-json 依赖项在您的类路径中(并且它在您的 POM 中的范围正确)?我尝试从我的 POM 中删除它并得到了与您相同的异常。
    • 有趣的是,当我在 pom.xml 中删除球衣依赖项的 provided 时,它会起作用。设置范围字段后,它会引发上述异常。
    【解决方案2】:

    user463324 的解决方案很好。通常,您可以使用此解决方案将 Java 对象转换为 JSON 并返回。它基于 Jackson 库。

    如果你想获取基于 JAXB 的 JSON,这里提供了一些配置选项,以便你可以控制如何序列化和反序列化。对于默认配置,您将获得字符串格式,就像您指出的问题一样。

    要实现更重要的 JSON 格式更改,您需要配置 Jersey JSON 处理器本身。可以在 JSONConfiguration 实例上设置各种配置选项。然后可以进一步使用该实例来创建 JSONConfigurated JSONJAXBContext,作为该区域的主要配置点。要将您的专用 JSONJAXBContext 传递给 Jersey,您最终需要实现一个 JAXBContext ContextResolver:

        @Provider
    public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    
        private final JAXBContext context;
        private final Set<Class> types;
        private Class[] ctypes = { JaxbPojo.class};
        public JAXBContextResolver() throws Exception {
            this.types = new HashSet(Arrays.asList(ctypes));
            this.context = new JSONJAXBContext(JSONConfiguration.natural().build(),
                    ctypes);
        }
    
        @Override
        public JAXBContext getContext(Class<?> objectType) {
            return (types.contains(objectType)) ? context : null;
        }
    }
    

    您可以参考jersey' official document了解详细信息。

    【讨论】:

    • 感谢您的回复。我现在会坚持 user463324 的方法。
    猜你喜欢
    • 1970-01-01
    • 2012-12-28
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 2011-10-14
    • 2015-01-05
    相关资源
    最近更新 更多