Jaxb 在泽西岛使用Gson代替Jackson

Jaxb 在泽西岛使用Gson代替Jackson,jaxb,jersey,jax-rs,jackson,gson,Jaxb,Jersey,Jax Rs,Jackson,Gson,我有一个使用和生成JSON对象的RESTful服务,我希望Jersey使用Gson而不是Jackson 如何做到这一点…?您需要编写和的自定义实现(可能在同一个类中)并向Jersey注册(如果您使用包扫描,@Provider注释就足够了)——非常像这样: @Provider @使用({MediaType.APPLICATION_JSON,“text/JSON”}) @产生({MediaType.APPLICATION_JSON,“text/JSON”}) 类GsonJsonProvider实现

我有一个使用和生成JSON对象的RESTful服务,我希望Jersey使用Gson而不是Jackson


如何做到这一点…?

您需要编写和的自定义实现(可能在同一个类中)并向Jersey注册(如果您使用包扫描,
@Provider
注释就足够了)——非常像这样:

@Provider
@使用({MediaType.APPLICATION_JSON,“text/JSON”})
@产生({MediaType.APPLICATION_JSON,“text/JSON”})
类GsonJsonProvider实现
MessageBodyReader,
MessageBodyWriter{。。。

您可以在这里找到一个完全有效的示例:

将会有一个工作实现,但是会有一些新的成就-比如
GsonUtil
只用于
公开
内容

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();
        }
    }
}
import java.io.IOException;
导入java.io.InputStream;
导入java.io.InputStreamReader;
导入java.io.OutputStream;
导入java.io.OutputStreamWriter;
导入java.lang.annotation.annotation;
导入java.lang.reflect.Type;
导入javax.ws.rs.Consumes;
导入javax.ws.rs.products;
导入javax.ws.rs.WebApplicationException;
导入javax.ws.rs.core.MediaType;
导入javax.ws.rs.core.MultivaluedMap;
导入javax.ws.rs.ext.MessageBodyReader;
导入javax.ws.rs.ext.MessageBodyWriter;
导入javax.ws.rs.ext.Provider;
@提供者
@产生(MediaType.APPLICATION_JSON)
@使用(MediaType.APPLICATION_JSON)
公共类GsonJerseyProvider实现MessageBodyWriter,
MessageBodyReader{
私有静态最终字符串UTF_8=“UTF-8”;
@凌驾
公共布尔值可读取(类类型、类型genericType、,
java.lang.annotation.annotation[]注释,MediaType(MediaType){
返回true;
}
@凌驾
公共对象读取自(类类型、类型genericType、,
注释[]注释,MediaType MediaType,
多值映射HttpHeader,InputStream entityStream)
抛出IOException{
InputStreamReader streamReader=新的InputStreamReader(entityStream,
UTF_8);
试一试{
从JSON(streamReader,genericType)返回GsonUtil.getInstance();
}catch(com.google.gson.JsonSyntaxException e){
//日志异常
}最后{
streamReader.close();
}
返回null;
}
@凌驾
公共布尔值可写(类类型、类型genericType、,
注释[]注释,MediaType(MediaType){
返回true;
}
@凌驾
公共长getSize(对象、类类型、类型genericType、,
注释[]注释,MediaType(MediaType){
返回-1;
}
@凌驾
public void writeTo(对象、类类型、类型genericType、,
注释[]注释,MediaType MediaType,
多值MAP HttpHeader,
OutputStream entityStream)引发IOException,
WebApplicationException{
OutputStreamWriter writer=新的OutputStreamWriter(entityStream,UTF_8);
试一试{
GsonUtil.getInstance().toJson(对象、genericType、编写器);
}最后{
writer.close();
}
}
}

您应该解决在pom中添加此依赖项的问题

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

org.zalando.phrs

Payara 4 我很难让我的自定义Gson
@Provider
使用嵌入GlassFish/Payara中的Jersey。在这种情况下,您必须将属性
Jersey.config.server.DisableOxyJSON
设置为
true

例如:

@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;
    }
}
帕亚拉5号
Payara 5支持API,因此继续使用Gson是没有意义的。我建议迁移到JSON-B。

我已经有了这样的提供者,但出于某种原因,它仍然使用Jackson(如果有帮助的话,我使用Glassfish 3.1.1)。如何向Jersey注册您的GsonProvider?您的服务器是否在启动时输出类似于
找到的提供程序类:your.Provider.class.name
?您的提供程序是否被调用,并且可能返回一些告诉Jersey它不兼容的内容?请尝试在提供程序类中的所有方法上添加断点。IMHO与Gson相比,这更容易如果你不能或不想注释你的模型类(与Jackson相比),那么更容易控制JSON的结构/格式。原因有很多:首先,根据最近的基准测试,Jackson的速度较慢。其次,它强制您对类进行注释,而不是简单地使用POJO。第三,Gson序列化了整个对象,而不仅仅是公共字段(在良好的设计实践中,您会得到许多重要的非公共字段)@StaxMan原因之一可能是Jackson ObjectMapper导致JDK 1中的核心转储。8@MosheBixenshpaner请链接到慢度——我没有看到任何。Gson一直在改进(2.1是不错的),但仍然落后于我所看到的一切。Jackson absolute不需要注释(另外,可以使用混合注释来避免注释值类)大多数情况下。最后:Jackson不需要公共字段;但是getter或更改默认可见性——我不同意默认情况下序列化所有私有字段是一种很好的做法;但是如果需要的话,Jackson是完全可以做到的。@StaxMan See一直在使用它,效果很好,但是……为什么
type.equals(genericType)呢
?似乎您总是可以使用
Type
,因为gson支持它,并且比
类拥有更多的信息。您是对的-应该使用
genericType
而不是equals检查-如果您愿意,您可以在github上创建一个pull请求。我还将使用我的测试用例测试它,然后编辑我的答案。感谢@sargue更新GsonJerseyProvider-我在这里更新了复制和粘贴解决方案-您可以在github链接下直接找到一个运行示例。github中不再存在项目
@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;
    }
}
new ClientConfig()
        .register(MyGsonProvider.class)
        .property("jersey.config.client.disableMoxyJson", true);