【问题标题】:Cannot get jersey 2 application to use custom jackson XmlMapper无法让球衣 2 应用程序使用自定义杰克逊 XmlMapper
【发布时间】:2015-11-25 15:28:07
【问题描述】:

我正在使用 Jersey 2.22.1 和 Jackson 2.6.3 编写 Web 应用程序。我的 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");
    }
}

如果我向 @Produces(MediaType.APPLICATION_JSON) 方法发出 GET 请求,一切都很好,并且使用了我的自定义映射器。但是,如果我对 @Produces(MediaType.APPLICATION_XML) 应用程序使用一些默认映射器而不是我的自定义映射器提出相同的请求。如果您有任何想法,请提供帮助。 谢谢!

【问题讨论】:

  • 您介意包含一些代码吗?最好从根本上剥离问题。

标签: java jersey jackson


【解决方案1】:

所以有几件事。首先,您需要的不仅仅是核心 Jackson xml 依赖项,还需要实际的 jaxrs provider

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

然后您应该排除 JAXB 提供程序,它是 Jersey 使用的默认提供程序。 (我在测试时离开它没有问题,但如果你不打算使用它,我会排除它)。它是由jersey-server 引入的,因此您应该明确声明jersey-server 并从中排除jersey-media-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。如here 所见,提供者为XmlMapper 寻找ContextResolver,而不是ObjectMapper

【讨论】:

    猜你喜欢
    • 2014-02-12
    • 1970-01-01
    • 2015-01-15
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    • 2014-02-13
    • 1970-01-01
    • 2017-06-16
    相关资源
    最近更新 更多