I have a RESTful service that consumes and produces JSON objects, and I would like Jersey to use Gson instead of Jackson.
How can this be done...?
Jersey uses Jackson internally to convert Java objects to JSON and vice versa.
Last benchmarks Jackson was the winner, but this time GSON is by far the fastest, with JSONP being a close second and then followed by Jackson and then JSON.
Gson is not deprecated.
GSON can use the Object definition to directly create an object of the desired type. While JSONObject needs to be parsed manually.
You need to write custom implementations of MessageBodyReader
and MessageBodyWriter
(possibly in the same class) and register with Jersey (if you use package scanning, the @Provider
annotation is enough) -- pretty much like JacksonJsonProvider
does it:
@Provider
@Consumes({MediaType.APPLICATION_JSON, "text/json"})
@Produces({MediaType.APPLICATION_JSON, "text/json"})
class GsonJsonProvider implements
MessageBodyReader<Object>,
MessageBodyWriter<Object> { ...
You can find a fully working example here: https://github.com/DominikAngerer/java-GsonJerseyProvider
There will be an working implementation of http://eclipsesource.com/blogs/2012/11/02/integrating-gson-into-a-jax-rs-based-application/ but with some new achievements - like an GsonUtil
for Expose
only things.
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class GsonJerseyProvider implements MessageBodyWriter<Object>,
MessageBodyReader<Object> {
private static final String UTF_8 = "UTF-8";
@Override
public boolean isReadable(Class<?> type, Type genericType,
java.lang.annotation.Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public Object readFrom(Class<Object> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException {
InputStreamReader streamReader = new InputStreamReader(entityStream,
UTF_8);
try {
return GsonUtil.getInstance().fromJson(streamReader, genericType);
} catch (com.google.gson.JsonSyntaxException e) {
// Log exception
} finally {
streamReader.close();
}
return null;
}
@Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public long getSize(Object object, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public void writeTo(Object object, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
try {
GsonUtil.getInstance().toJson(object, genericType, writer);
} finally {
writer.close();
}
}
}
I had a hard time to get my custom Gson @Provider
working with Jersey embedded in GlassFish / Payara. In that case you must set the property jersey.config.server.disableMoxyJson
to true
.
For example:
@ApplicationPath("/api")
public class MyApplication extends Application {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> props = new HashMap<>();
props.put("jersey.config.server.disableMoxyJson", true);
return props;
}
}
See also:
Same thing goes for a Jersey client:
new ClientConfig()
.register(MyGsonProvider.class)
.property("jersey.config.client.disableMoxyJson", true);
Payara 5 supports the JSON Binding API, so it does not make sense to keep using Gson. I would advice to migrate to JSON-B.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With