为什么Apache CXF会错误地将String转换为JSON?

时间:2011-12-01 10:32:16

标签: json apache cxf jax-rs

我遇到了意外的Apache CXF行为:当我从我的服务返回String时,它没有正确转换为JSON - 而不是在字符串周围添加双引号,Apache CXF按原样返回。

我的服务:

@Path(ROOT_URL)
@Produces(MediaType.APPLICATION_JSON)
public class SomeRestService {

    @GET
    @Path(SERVICE_URL)
    public Response getString() {
        return Response.ok("OK").build();
    }

}

Apache CXF配置的一部分:

<jaxrs:server id="RestService" address="/api">
        <jaxrs:serviceBeans>
            <bean class="org.example.project.ws.rest.SomeRestService" />
        </jaxrs:serviceBeans>
        <jaxrs:extensionMappings>
            <entry key="json" value="application/json" />
        </jaxrs:extensionMappings>
</jaxrs:server>

你能帮助我理解为什么这样工作以及如何告诉CXF返回字符串真的是JSON吗?

1 个答案:

答案 0 :(得分:1)

JSON是一种序列化复杂对象的方法,Java的字符串(实际上)不是。这意味着无法直接将字符串序列化为JSON对象;序列化程序只是不知道将它映射到什么,因此挽救(或者说它不会为String启用它自己)。对此有两种可能的解决方法。

选项1:使用不同的内容类型

字符串的自然映射是发送text/plain类型的内容,而不是application/json。这个映射内置到CXF(以及任何其他JAX-RS实现)中,它很容易使它工作。 (我更喜欢将产品和消费注释放在个别方法而不是整体课程上,但这是个人选择。)

@Path(ROOT_URL)
public class SomeRestService {
    @GET
    @Path(SERVICE_URL)
    @Produces("text/plain")
    public Response getString() {
        return Response.ok("OK").build();
    }
}

选项2:将字符串换行到带注释的JAXB对象

如果您确实希望数据以JSON格式显示,则需要提供其他元数据。通过添加具有JAXB注释的包装类来实现此目的的绝大多数最简单的方法,然后允许Jettison(CXF使用的序列化库)将正确的东西吐出来。在下面的示例中,我使用的是静态内部类,因为它使(基本上无聊的)类靠近使用它的唯一位置,但是YMMV;它确实必须是一个带注释的公共“结构”(即,一个带有无参数构造函数的类以及公共字段或适当的微不足道的getter和setter)。

@Path(ROOT_URL)
public class SomeRestService {
    @GET
    @Path(SERVICE_URL)
    @Produces("application/json")
    public Response getServiceMessage() {
        ServiceMessage result = new ServiceMessage();
        result.message = "OK";
        return Response.ok(result).build();
        // Or: return Response.ok(result,"application/json").build();
        // Or: return Response.ok(result).type("application/json").build();
    }

    @XmlRootElement  // This annotation _is_ required, can be customized further
    public static class ServiceMessage {
        @XmlElement  // This annotation isn't required, but documents intention
        public String message;
    }
}

我省略了为ServiceMessage构建一整套构造函数,这使得使用它比它可能稍微不方便;代码(几乎)纯粹是简单的骨头。