当前位置: 首页 > 知识库问答 >
问题:

对Jersey使用自定义的ObjectWriter

高鸿振
2023-03-14

我正在开发一个REST网络服务。泽西岛作为 jax-rs 提供程序,杰克逊作为序列化/反序列化。我还基于Retrofit2开发客户端。

我的类层次结构是由第三方库提供的,所有类都是从根基类BaseObject派生出来的。其中一些类有不受欢迎的getter,例如我想在序列化时忽略它们(请注意,重要的是它们根本没有被序列化,在反序列化上使用FAIL_ON_UNKNOWN_PROPERTIES在我的例子中是不够的)。

我已经在使用Mixins的< code>BaseClass上使用了Jackson @JsonFilter。据我所知,要应用过滤器,必须使用以下方法:

new ObjectMapper().writer(filterProvider).writeValueAsString...

到目前为止,一切都很好:从生成的json中成功过滤了不需要的属性。

现在我必须配置Jersey和Retrofit2来使用我定制的json序列化器/反序列化器。

对于Jersey,可以使用实现上下文解析器的提供程序类配置序列化/反序列化

类似地,在改装2中,通过使用改装.Builder().addConverterFactory(JacksonConverterFactory.create(objectMapper)),可以自定义序列化/反序列化。

问题是new ObjectMapper(). Writ(filterProvider)ObjectWriter类型的,而不是ObjectMapper类型的。如何告诉泽西和Retrofit2使用使用我的过滤器的自定义ObjectWriter


共有1个答案

曾承弼
2023-03-14

从Jackson的2.6版本开始,它为ObjectMapper提供了“setFilterProvider”方法。我没有尝试过,但文档对此有描述:https://faster XML . github . io/Jackson-databind/javadoc/2.6/com/faster XML/Jackson/databind/object mapper . html # setFilterProvider-com . faster XML . Jackson . databind . ser . filter provider-。我想你可以试试,因为这个描述符合你的情况。

我用Jersey 2.7和Jackson 2.9.5构建了一个测试服务。它运行良好,但你必须知道一些技巧来运行它。

在pom.xml添加泽西和杰克逊:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey</groupId>
            <artifactId>jersey-bom</artifactId>
            <version>${jersey.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>${jackson.version}</version>
    </dependency>
</dependencies>
<properties>
    <jersey.version>2.7</jersey.version>
    <jackson.version>2.9.5</jackson.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

您必须定义此依赖关系:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
    </dependency>

这是强制性的。

web.xml您必须参考服务的配置:

<web-app version="2.5"
     xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>org.glassfish.jersey.server.ResourceConfig</param-name>
        <param-value>com.home.MyApplication</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

MyApplication.java:

package com.home;

import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;

import javax.ws.rs.ApplicationPath;

@ApplicationPath("/webapi")
public class MyApplication extends ResourceConfig {

    public MyApplication() {

        register(ObjectMapperProvider.class);
        register(JacksonFeature.class);
        register(MyResource.class);

    }
}

使用自定义ObjectMapperProvider,您必须注册JacksonFeature.class,因为没有它,泽西不会使用自定义ObjectMapperProvider。

ObjectMapperProvider.java:

package com.home;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper>{

    final ObjectMapper defaultObjectMapper;

    public ObjectMapperProvider() {
        defaultObjectMapper = createDefaultMapper();
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {return defaultObjectMapper;}

    public static ObjectMapper createDefaultMapper() {

        final ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.setFilters(new SimpleFilterProvider().addFilter("dataFilter", SimpleBeanPropertyFilter.serializeAllExcept("region", "city")));
        return mapper;

    }
}

要定义过滤器,请使用“setFilters”方法。此方法已弃用,但泽西岛名为“jersey-hk2”的库不知道新方法“setFilterProvider”并引发异常。使用旧方法,一切都很好。

带有@JsonFilter的业务对象:

@JsonFilter("dataFilter")
public class SimpleData {

    @JsonProperty("name")
    String firstName;

    @JsonProperty("secondName")
    String lastName;

    @JsonProperty("country")
    String country;

    @JsonProperty("region")
    String region;

    @JsonProperty("city")
    String city;

    @JsonProperty("genre")
    String genre;

    public SimpleData() {

        this.firstName = "Bryan";
        this.lastName = "Adams";

        this.country = "Canada";
        this.region = "Ontario";
        this.city = "Kingston";
        this.genre = "Rock";

    }

    public String getFirstName() {    return firstName;       }
    public void setFirstName(String firstName) {  this.firstName = firstName;  }
    public String getLastName() {   return lastName;    }
    public void setLastName(String lastName) {  this.lastName = lastName;       }
    public String getCountry() {    return country;    }
    public void setCountry(String country) {  this.country = country;      }
    public String getRegion() {   return region;     }
    public void setRegion(String region) {   this.region = region;       }
    public String getCity() {  return city;     }
    public void setCity(String city) {   this.city = city;     }
    public String getGenre() {   return genre;      }
    public void setGenre(String genre) {    this.genre = genre;     }
}

MyResource.java:

@Path("myresource")
public class MyResource {


    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public SimpleData getIt() {

        return new SimpleData();

    }
}

过滤后的结果:

 类似资料:
  • 问题内容: 如果要以非安全方式访问某些方法,我想限制它们。我正在创建一个@Secure批注,该批注检查请求是否通过安全通道发送。但是,我无法创建一个可注入的方法来捕获请求的HttpContext。 我使用的是Dropwizard框架,因此提供程序的初始化应该像下面这样简单: 用法: 在这一点上,我假设HttpContext Injectable在某种方法上不起作用,但是我对可以用来实现此注释的其他

  • 我写Web应用程序使用泽西2.22.1和杰克逊2.6.3。我的pom.xml是这样的: 目标是为JSON和XML映射使用不同的自定义ObjectMapper。我创建了两个提供程序类:JSONMapperProvider 和XMLMapperProvider 它们都在同一个包中,该包在应用程序资源类中注册 若我向@products(MediaType.APPLICATION_JSON)的方法发出GE

  • 问题内容: 我正在尝试在JFrame中使用特殊字体,但遇到了问题。我有一个这样定义的JLabel: 并且我有一个名为CUSTOMFONT-MEDIUM.TTF(TrueType字体)的文件,但是编写了以下内容: 代码会编译,并且一切正常,除了不会显示“ lab”,因此没有文本。我想这是因为我从未指定字体大小,但是我所做的任何尝试都失败了。有人可以帮我吗? 问题答案: 您创建的字体必须先在中注册,以

  • 问题内容: 我正在努力实现以下目标。 从Request中读取自定义标头及其值: 现在,在响应时,我想在HTTP响应中返回相同的标头对。 我正在使用JAX-RS Web服务的Jersey 2.0实现。 当我发送请求URL时,也会传递请求标头(目前,虽然是Firefox插件-对其进行硬编码)。 收到对该URL的请求后,将调用以下方法: 我该如何实现?任何指针都很棒! 问题答案: 只需注入a 作为方法参

  • 我试图创建一个音频捕获活动,所以我从android文档中复制了这个类,如下所示 在我的xml页面中,我试图创建一个id为麦克风的RecordButton。类似这样的东西 现在,当我尝试运行该应用程序时,会出现以下输出

  • 下面是如何配置应用程序的 问题是在应用程序启动期间,我得到以下错误 并且有很长的堆栈错误堆栈和描述 null 我刚试过用两个自定义方法param注入,那也不起作用