gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-11-01 01:50:43 28 4
gpt4 key购买 nike

我正在使用 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>

目标是使用不同的自定义 ObjectMappers 进行 JSON 和 XML 映射。我创建了两个提供者类: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);
}
}
}
}

它们都在同一个包中,在Application资源类中注册

@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) 应用程序提出相同的请求,则使用一些默认映射器而不是我的自定义映射器。如果您有任何想法,请提供帮助。谢谢!

最佳答案

所以有几件事。首先,您需要的不仅仅是核心 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

关于java - 无法让 jersey 2 应用程序使用自定义 jackson XmlMapper,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33920349/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com