Monday, November 15, 2010

JAX-RS is really nice for writing REST services. I'm using Jersey 1.3, with Guice 2.0 and jersey-guice to configure things. However, the Jersey JSON provider is horrible. It messes up writing empty and single element arrays, and it writes boolean and numerical values as strings. My first hack around that was to return a JSON string instead of the objects, doing the conversions in-line using Jackson 1.5. That was ugly, so I overwrote META-INF/services/javax.ws.rs.ext.MessageBodyReader and META-INF/services/javax.ws.rs.ext.MessageBodyWriter in the Jersey jar, replacing the Jersey JSON providers with org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider, and it was much better.

I also use the Jersey REST client to talk to Facebook. However, Facebook returns text/javascript;charset=UTF-8 as the content-type, which is not recognized by either the Jersey JSON provider, or the Jackson JAX-RS JSON provider. Again, the first thing I did was to get the content as an InputStream, which I sent to Jackson for object binding. Then, I figured that I could just extend the Jackson JSON provider to accept text/javascript and use that class as the JSON provider.

@Provider
@Consumes({MediaType.APPLICATION_JSON, "text/json", "text/javascript"})
@Produces({MediaType.APPLICATION_JSON, "text/json"})
public class MyJaxbJsonProvider extends JacksonJaxbJsonProvider {
@Override
protected boolean isJsonType(MediaType mediaType) {
if (mediaType != null && "javascript".equals(mediaType.getSubtype()))
return true;
return super.isJsonType(mediaType);
}
}

Now, the code no longer has ugly hacks for JSON. However, any time I get a new Jersey jar, I'll have to overwrite the provider list in the jar, which is ugly. Perhaps I could put my own javax.ws.rs.ext.MessageBodyReader and javax.ws.rs.ext.MessageBodyWriter in a jar, and have it take precedence, but it didn't work the first time I tried it. It might depend on the classpath order of the jars, and having to use the classpath order of jar files to override things is also ugly.

Also on JSON, RFC-4627 says that slashes may be backslash quoted, though the example in section 8 does not backslash quote the slashes. The JSON from Facebook does backslash quote the slashes, but the JSON produced by Jackson does not. I wonder why backslash quoted slashes were explicitly included in the JSON specification. Perhaps it was inherited from Javascript, in which case I wonder why it was that way in Javascript. My only guess is that it had something to do with regular expressions, if it was from Javascript. Otherwise, it just seems weird.

No comments:

Post a Comment