web-dev-qa-db-fra.com

Utiliser Gson au lieu de Jackson à Jersey

J'ai un service RESTful qui consomme et produit des objets JSON, et j'aimerais que Jersey utilise Gson au lieu de Jackson.

Comment cela peut-il être fait...?

26

Vous devez écrire des implémentations personnalisées de MessageBodyReader et MessageBodyWriter (éventuellement dans la même classe) et vous enregistrer auprès de Jersey (si vous utilisez l'analyse de package, l'annotation @Provider suffit) - à peu près comme JacksonJsonProvider fait-il:

@Provider
@Consumes({MediaType.APPLICATION_JSON, "text/json"})
@Produces({MediaType.APPLICATION_JSON, "text/json"})
class GsonJsonProvider implements
    MessageBodyReader<Object>,
    MessageBodyWriter<Object> { ...
25
Philipp Reichart

Vous pouvez trouver un exemple pleinement fonctionnel ici: https://github.com/DominikAngerer/Java-GsonJerseyProvider

Il y aura une implémentation fonctionnelle de http://eclipsesource.com/blogs/2012/11/02/integrating-gson-into-a-jax-rs-based-application/ mais avec quelques nouvelles réalisations - comme un GsonUtil pour Expose seulement des choses.

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();
        }
    }
}
21
DominikAngerer

Vous devriez résoudre simplement en ajoutant cette dépendance dans votre pom

<dependency>
    <groupId>org.zalando.phrs</groupId>
    <artifactId>jersey-media-json-gson</artifactId>
    <version>0.1</version>
</dependency>

Ici vous pouvez trouver le dépôt avec le code source: https://github.com/zalando/jersey-media-json-gson

1
Matteo Pierro

J'ai eu du mal à utiliser mon Gson personnalisé @Provider avec Jersey intégré à GlassFish/Payara. Dans ce cas, vous devez définir la propriété jersey.config.server.disableMoxyJson sur true.

Par exemple:

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

Voir également:

Même chose pour un client Jersey:

new ClientConfig()
        .register(MyGsonProvider.class)
        .property("jersey.config.client.disableMoxyJson", true);
1
Jasper de Vries