Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Apache CXF将字符串错误地转换为JSON?_Json_Apache_Cxf_Jax Rs - Fatal编程技术网

为什么Apache CXF将字符串错误地转换为JSON?

为什么Apache CXF将字符串错误地转换为JSON?,json,apache,cxf,jax-rs,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() { r

我面临着意外的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吗?

JSON是一种序列化复杂对象的方法,而Java的字符串(实际上)不是。这意味着无法直接将字符串序列化为JSON对象;序列化程序只是不知道将其映射为什么,因此退出(或者更确切地说,它不为
String
启用自身)。有两种可能的修复方法

选项1:使用不同的内容类型 字符串的自然映射是到
text/plain
类型的消息内容,而不是
application/json
。这种映射内置于CXF(以及任何其他JAX-RS实现)中,并且非常容易实现。(我更喜欢将生成和使用注释放在单个方法上,而不是放在整个类上,但这是个人的选择。)

选项2:将字符串包装在JAXB注释的对象中 如果您确实希望数据以JSON的形式出现,则需要提供额外的元数据。最简单的方法是添加一个具有JAXB注释的包装类,然后允许抛弃(CXF使用的序列化库)抛出正确的内容。在下面的示例中,我使用了一个静态的内部类,因为它使一个(基本上很无聊的)类靠近唯一使用它的地方,但是YMMV;但它必须是一个带注释的公共“struct”(即,具有无参数构造函数和公共字段或适当的普通getter和setter的类)


我省略了为
ServiceMessage
构建一整套构造函数,这使得使用它的便利性略低于可能的程度;代码(几乎)完全是简单的。

为什么返回
响应
?这是一种复杂的方法。@donal fellows如果不使用Response,它甚至对我来说都不起作用:(真的,你不应该对这些琐碎的东西使用Response;当你想要一个非200 HTTP响应或者必须在内容类型处理中做一些真正复杂的事情时,你需要一个响应。返回“OK”两者都不是!@donal fellows是的,在某些情况下,我确实需要
Response
来设置非200状态(例如验证失败时)。我刚刚发布了带有错误处理的非简化版本的真实代码。好吧,您仍然需要进行以下更改;您的基本问题是字符串无法直接序列化为JSON。不过,我将更新我的答案以反映响应的使用。
@Path(ROOT_URL)
public class SomeRestService {
    @GET
    @Path(SERVICE_URL)
    @Produces("text/plain")
    public Response getString() {
        return Response.ok("OK").build();
    }
}
@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;
    }
}