Java Jersey:JSON和StringMessageProvider冲突,应用程序/JSON方法生成无效的JSON

Java Jersey:JSON和StringMessageProvider冲突,应用程序/JSON方法生成无效的JSON,java,json,rest,jersey,jax-rs,Java,Json,Rest,Jersey,Jax Rs,我在jetty+jersey上有一个jax-rsweb服务,并尝试了不同的JSON消息提供者(例如Jackson和Gson)。 对于所有这些,POJO JSON都可以很好地工作,但是像这样的方法: @GET @Path("test") @Produces(MediaType.APPLICATION_JSON) public String test() { return "This string should be \"quoted\" by message writer"; } 生产线

我在jetty+jersey上有一个jax-rsweb服务,并尝试了不同的JSON消息提供者(例如Jackson和Gson)。 对于所有这些,POJO JSON都可以很好地工作,但是像这样的方法:

@GET
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public String test() {
    return "This string should be \"quoted\" by message writer";
}
生产线

This string should be "quoted" by message writer
这当然不是有效的JSON,并导致浏览器的ajax调用失败。 我希望是这样

"This string should be \"quoted\" by message writer"
之所以如此神奇,是因为StringMessageProvider(基本类型的内部jersey提供程序之一)具有/product/Consume注释。我不想侵入泽西岛的内部供应商。我想首先强制jersey使用JSON提供程序


有什么想法吗?

您生成的JSON无效(您可能需要使用验证)

因此,有效的JSON可以是:

{"msg":"This string should be \"quoted\" by message writer"}

["This string should be \"quoted\" by message writer"]
每个JSON的Java代码:

@GET
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> test() {
    Map<String, String> map = new HashMap<String, String>();
    map.put("msg", "This string should be \"quoted\" by message writer");
    return map;
}

@GET
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> test() {
    return Arrays.asList("This string should be \"quoted\" by message writer");
}
@GET
@路径(“测试”)
@产生(MediaType.APPLICATION_JSON)
公共地图测试(){
Map Map=newhashmap();
put(“msg”,“此字符串应由消息编写器引用”);
返回图;
}
@得到
@路径(“测试”)
@产生(MediaType.APPLICATION_JSON)
公共地图测试(){
return Arrays.asList(“此字符串应由消息编写器引用”);
}

注意:我正在将RESTEasy 3.0.8与Jackson 2.4.1一起使用

因此,在阅读jersey文档并进行一些调试后发现:

  • 是的,自定义邮件阅读器/编写器具有更高的优先级,但是
  • 选择“合适的”提供者(从正确的提供者开始)后,jersey通过自定义比较对其进行排序,首先检查“类型”距离
因此,使用方法返回类型“String”和JSON消息提供程序MIME类型通配符(/),它通过比较String String 通过添加非通用自定义消息提供程序解决了此问题,例如:

public class StringProvider extends GsonProvider<String> {
    public StringProvider() {}
}
公共类StringProvider扩展了GsonProvider{
公共StringProvider(){}
}
(其中,
GsonProvider实现MessageBodyReader,MessageBodyWriter


之后,返回的字符串被转义为正确的JSON,并被浏览器的ajax调用处理程序识别。

对不起,您错了。1) 表示:…“在JSON中,它们采用以下形式:…a)对象是无序的名称/值对集…b)数组是有序的值集合…c)值可以是双引号中的字符串,也可以是数字,…”。您还可以查看最新的JSON RFC,其中说“string”值是有效的JSON。@tuxSlayer-您返回的原始字符串作为JSON中的顶级对象无效。Paul Vargas正在返回一个JSON对象(字符串映射->对象)。RFC7159说字符串是有效的JSON,但仅在某些位置。单个原始字符串是无效的JSON。让我们一起来读:)JSON文本是一个令牌序列。标记集包括六个结构字符、字符串、数字和三个文字名称。JSON文本是一个序列化的值。请注意,以前的某些JSON规范将JSON文本约束为对象或数组。只生成调用JSON文本的对象或数组的实现将具有互操作性,因为所有实现都将接受这些对象或数组作为一致的JSON文本
JSON text=ws-value-ws
,。。。然后遵循“价值”定义)好的,你说的是7159,这是一个提议的标准——正如RFC本身所解释的:淘汰:46277158 2014年3月。它仅仅出现了几个月,而且您所谈论的库不太可能支持该标准。之前的4627标准不允许原始字符串作为顶层,正如您在评论中特别提到的:请注意,以前的JSON规范将JSON文本约束为对象或数组。好的,同意。但解决方案比我最初认为的更简洁、更简单,而且比返回
Map
更优雅。这太棒了。不需要使用Gson。我也添加了一个StringMessageBodyWriter,它实现了MessageBodyWriter,并使用Jackson实现writeTo。