有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何通过Jackson传递原始JSON?

我们有一整套JAX-RSREST服务运行在ApacheCxf和Jackson之上。 我们使用JAXB注释将POJO编组为JSON,效果非常好

然而,我们有一两个地方需要返回原始JSON字符串(从Redis缓存获取)

Jackson总是将字符串用双引号括起来,并转义其中的所有双引号,例如

@GET @Produces("application/json")
public Response getData() {

    String json = ...get from Redis...
    return Response.ok(json,"application/json").build() 
}

给我们

"{\"test\":1}"

而不是

{"test":1}

我尝试过多种方法,将RawSerializer(String.class)添加到对象映射器中,但没有任何效果。唯一有效的方法是,如果我将媒体类型设置为纯字符串,这绕过了Jackson,但不好,因为我返回了错误的内容类型

return Response.ok(json,"text/plain").build() 

工作正常,但效果很差(内容类型错误,导致调用我们的.Net WCF应用程序出错)


共 (3) 个答案

  1. # 1 楼答案

    终于找到了解决办法。诀窍是扩展JacksonJsonProvider(我们在CXF中使用它来强制它使用Jackson而不是抛弃),并告诉它在处理原始字符串时完全绕过Jackson:

    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType){
        if (String.class.equals(type)) {
            //pass strings as-is, they are most likely cached JSON responses
            return false;
        } else {
            return true;
        }
    }
    

    效果很好

  2. # 2 楼答案

    在这种情况下,最好的选择是使用返回类型String,因为问题不在于Jackson,他的工作是从对象中生成JSON,而不是按原样传递字符串,而是在于JAX-RS,它不调用Jackson。默认的Jackson支持的JSON提供程序将按原样传递String值(对于byte[],同上),无需任何处理

    值得一提的是,实际上还有JsonGenerator.writeRaw()方法,它允许在OutputStream中嵌入文本,但JAX-RS实现使用ObjectMapper,而不是低级抽象

  3. # 3 楼答案

    ObjectMapper不工作了?应该是:

    ObjectMapper mapper = new ObjectMapper()
    MyObj obj = MyObj();
    ...set values...
    String jsonRes = mapper.writeValueAsString(obj);
    return Response.ok(jsonRes, MediaType.APPLICATION_JSON).build();