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

无法使jersey 2应用程序使用自定义jackson XmlMapper

夏谦
2023-03-14

我写Web应用程序使用泽西2.22.1和杰克逊2.6.3。我的pom.xml是这样的:

<!-- JERSEY -->
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.22.1</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>2.22.1</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.22.1</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-multipart</artifactId>
        <version>2.22.1</version>
    </dependency>
    <dependency>
        <groupId>asm</groupId>
        <artifactId>asm</artifactId>
        <version>3.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.woodstox</groupId>
        <artifactId>woodstox-core-asl</artifactId>
        <version>4.4.1</version>
    </dependency>
    <!-- JACKSON -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.6.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.6.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.6.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.6.3</version>
    </dependency>

目标是为JSON和XML映射使用不同的自定义ObjectMapper。我创建了两个提供程序类:JSONMapperProvider

    @Provider
    @Produces(MediaType.APPLICATION_JSON)
    public class JSONMapperProvider implements ContextResolver<ObjectMapper> {
    private static ObjectMapper objectMapper;

    public JSONMapperProvider() {
    init();
    }

    public static void init() {
    if (objectMapper == null) {
        objectMapper = new ObjectMapper();
        // SERIALIZATION
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
            .configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
            .setSerializationInclusion(Include.NON_NULL)
            .setSerializationInclusion(Include.NON_EMPTY);
        // DESERIALIZATION
        objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true)
            .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
        // set up ISO 8601 date/time stamp format:
        ObjectMapperProvider.DATE_FORMAT_ISO8601.setTimeZone(TimeZone.getTimeZone("GMT"));
        objectMapper.setDateFormat(ObjectMapperProvider.DATE_FORMAT_ISO8601);
        // Custom deserializer for date which helps deserialization of date
        // without time
        SimpleModule dateDeserializerModule = new SimpleModule("DateDeserializerModule", Version.unknownVersion());
        dateDeserializerModule.addDeserializer(Date.class, new CustomJsonDateDeserializer());
        //objectMapper.registerModule(dateDeserializerModule);
    }
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
    System.out.println("JSONMapperProvider.getContext() called with type: "
        + type);
    return objectMapper;
    }

    private static class CustomJsonDateDeserializer extends JsonDeserializer<Date> {
    @Override
    public Date deserialize(JsonParser jsonparser, DeserializationContext deserializationcontext) throws IOException, JsonProcessingException {
        String date = jsonparser.getText();
        try {
        return DateUtil.parseDate(date);
        } catch (ParseException e) {
        throw new RuntimeException(e);
        }
    }
    }
}

和XMLMapperProvider

    @Provider
    @Produces({ MediaType.APPLICATION_XML })
    public class XMLMapperProvider implements ContextResolver<ObjectMapper>     {

    private static ObjectMapper objectMapper;

    public XMLMapperProvider() {
    init();
    }

    public static void init() {
    if (objectMapper == null) {
        JacksonXmlModule module = new JacksonXmlModule();
        module.setDefaultUseWrapper(false);
        objectMapper = new XmlMapper(module);
        // SERIALIZATION
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
            .configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
            .setSerializationInclusion(Include.NON_NULL)
            .setSerializationInclusion(Include.NON_EMPTY);
        // DESERIALIZATION
        objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true)
            .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
        // set up ISO 8601 date/time stamp format:
        ObjectMapperProvider.DATE_FORMAT_ISO8601.setTimeZone(TimeZone.getTimeZone("GMT"));
        objectMapper.setDateFormat(ObjectMapperProvider.DATE_FORMAT_ISO8601);
        // Custom deserializer for date which helps deserialization of date
        // without time
        SimpleModule dateDeserializerModule = new SimpleModule("DateDeserializerModule", Version.unknownVersion());
        dateDeserializerModule.addDeserializer(Date.class, new CustomJsonDateDeserializer());
        objectMapper.registerModule(dateDeserializerModule);
    }
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
    System.out.println("XMLMapperProvider.getContext() called with type: "
        + type);
    return objectMapper;
    }

    private static class CustomJsonDateDeserializer extends JsonDeserializer<Date> {
    @Override
    public Date deserialize(JsonParser jsonparser, DeserializationContext deserializationcontext) throws IOException, JsonProcessingException {
        String date = jsonparser.getText();
        try {
        return DateUtil.parseDate(date);
        } catch (ParseException e) {
        throw new RuntimeException(e);
        }
    }
    }
}

它们都在同一个包中,该包在应用程序资源类中注册

@ApplicationPath("resources")
public class CCRestResources extends ResourceConfig {
    public CCRestResources() {
        register(JacksonFeature.class);
        packages("com.cc.rest.jersey");
    }
}

若我向@products(MediaType.APPLICATION_JSON)的方法发出GET请求,那个么一切都很好,并且使用了我的自定义映射器。但如果我向@products(MediaType.APPLICATION\uxml)应用程序的emthod发出相同的请求,则使用一些默认映射器,而不是我的自定义映射器。如果你有任何想法,请帮忙。谢谢

共有1个答案

吴嘉禧
2023-03-14

所以一些事情。首先,您需要的不仅仅是核心Jackson xml依赖项,还需要实际的jaxrs提供程序

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-xml-provider</artifactId>
    <version>${jackson2.version}</version>
</dependency>

然后您应该排除JAXB提供程序,它是Jersey使用的默认提供程序。(我在测试时留下它并没有问题,但如果您不打算使用它,我会将其排除在外)。它由jersey服务器拉入,因此您应该明确声明jersey服务器,并从中排除jersey媒体jaxb

<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-server</artifactId>
    <version>${jersey2.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-jaxb</artifactId>
        </exclusion>
    </exclusions>
</dependency>

然后,您将需要注册JacksonJaxbXMLProvider(如果您不需要或计划使用JAXB注释,则只需注册JacksonXMLProvider)。

public CCRestResources() {
    register(JacksonFeature.class);
    register(JacksonJaxbXMLProvider.class);
    packages("com.cc.rest.jersey");
}

最后,您需要将ContextResolver参数化为XmlMapper类型,而不是ObjectMapper。如图所示,提供程序为XmlMapper查找ContextResolver,而不是ObjectMapper

 类似资料:
  • 问题内容: 我正在使用Jersey 2.22.1和Jackson 2.6.3编写Web应用程序。我的pom.xml看起来像这样: 目标是将不同的自定义ObjectMappers用于JSON和XML映射。我创建了两个提供程序类:JSONMapperProvider 和XMLMapperProvider 它们都在同一包中,并在Application资源类中注册 如果我向@Produces(MediaT

  • 问题是,就应用程序生命周期处理和易于使用而言,这种体系结构是否可以被认为是安全的? Update:每次创建新的活动并希望获得数据时,它可以获得ApplicationContext的BehaviorSubject,然后订阅它,Subject将发出最后发出的值;我为什么要这样做?例如。假设你有新闻项目,你获取了新闻提要,你想启动后台任务来获取新闻项目的全部内容,在这种情况下,我可以在你滚动新闻列表时开

  • 我正在使用Appium来自动化一个iOS的移动应用程序,对于一些元素,Appium检查员无法找到XPATH。 我已经读到,这是因为Appium使用仪器,只能定位iOS标准对象,而不是自定义对象。 我非常感谢您在这方面的任何建议/帮助。 示例:需要在下面的示例中找到单选按钮的XPATH app页面屏幕

  • 然后我的看起来像 我的问题是为空。知道怎么了吗?另外,我可以绑定我的注入器的实例而不是绑定类吗?这样,我就可以构造将数据作为参数传递的实例。

  • 问题内容: 我知道,只需在屏幕上设置元素的自定义字体即可。 我想知道如何使用swift为整个应用程序设置它。(破解将是针对应用程序的每个元素执行我所知道的操作,但这只会成为可维护性的噩梦) 我看到这个问题已经用Objective-C标签问过,如何在不指定大小的情况下为整个iOS应用设置自定义字体,但我对Objective-C不够熟悉,不足以将代码移植到Swift 问题答案: 您可以设置UILabe