简体   繁体   中英

How to pass raw JSON via Jackson?

We have a whole set of JAX-RS REST services running on top of Apache CXF and Jackson. We use JAXB annotations to take care of marshalling POJOs to JSON, works great.

However, we have one or two places where we want to return raw JSON string (that we fetch from a Redis cache).

Jackson always wraps the string in double quotes and escapes all the double quotes in it, eg

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

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

gives us

"{\"test\":1}"

instead of

{"test":1}

I've tried multiple things, adding RawSerializer(String.class) to the Object mapper, nothing works. The only thing that works is if I set the media type to plain string, which bypassed Jackson, but is not good, since I am returning the wrong content type

ie

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

works, but poorly (wrong content type, which screws up .Net WCF apps that call us)

Found the solution finally. The trick was to extend the JacksonJsonProvider (which we use in CXF to force it to use Jackson instead of Jettison) and tell it to bypass Jackson altogether when dealing with raw Strings:

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;
    }
}

Works perfectly.

ObjectMapper isn't working? Should just be:

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

In such case, your best bet is to use return type of String , since the issue is not with Jackson -- whose job is to produce JSON out of Objects, not pass Strings as is -- but with JAX-RS which is not to call Jackson. Default Jackson-backed JSON provider will pass String value exactly as is (ditto for byte[] ), without any processing.

For what it is worth, there is actually JsonGenerator.writeRaw() method as well, which allows embedding literal text in OutputStream , but JAX-RS implementations use ObjectMapper , not low-level abstractions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM