我有一个带有POST /items
端点的JSON REST API,它需要一个像:
{"name": "item_name", "timestamp": "2018-01-01T01:01:01.001"}
我需要从部署在WildFly10上的JEE7应用程序调用此端点。
为了用Java建模对象,我定义了一个简单的DTO类:
class ItemDTO {
private String name;
private LocalDateTime timestamp;
// default constructor and getters/setters omitted for brevity
}
默认情况下,LocalDateTime的序列化会导致复杂的JSON对象而不是ISO8601字符串。
根据我在网络上发现的内容,我添加了我的依赖项:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
使用jackson.version = 2.7.4
ClientBuilder builder = ClientBuilder.newBuilder()
.register(new RequestLogger())
.register(
new JacksonJsonProvider(
new ObjectMapper()
.registerModule(new JavaTimeModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false)
.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"))
, DEFAULT_ANNOTATIONS)
);
上面的代码将clientBuilder配置为构建配备了ObjectMapper的客户端,该对象将Java8日期/时间类型序列化为ISO8601字符串。
Response creation = builder.build()
.target("http://localhost:8080/my-api/v1.0/items")
.request().accept(MediaType.APPLICATION_JSON)
.post(Entity.entity(itemDTO, MediaType.APPLICATION_JSON));
意外地此请求失败,因为LocalDateTime
中包含的ItemDTO
仍然被序列化为复杂的JSON对象。
N.B。:我的REST API完全能够将ISO8601字符串反序列化为LocalDateTime
N.B。:如果没有在容器内运行,那么发出POST请求的代码就能完美运行(即LocalDateTime被序列化为ISO8601)
答案 0 :(得分:0)
“如果不在容器内运行,则使POST请求的代码完美无缺”
您注册客户端的JacksonJsonProvider
很可能不是正在使用的ObjectMapper
。在容器中,RESTEasy已经有一个自动注册到客户端的Jackson模块,这就是正在使用的模块。
您可以使用ContextResolver
而不是配置ObjectMapper
并将其传递给提供商。提供程序将查找此解析程序并从那里获取@Provider
public class ObjectMapperResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper mapper;
public ObjectMapperResolver() {
mapper = new ObjectMapper();
// configure mapper
}
@Override
public ObjectMapper getContext(Class<?> cls) {
return mapper;
}
}
。
ClientBuilder builder = ClientBuilder.newBuilder()
.register(ObjectMapperResolver.class)
然后只需向客户注册解析器。
Array.findIndex()
如果 这是我怀疑的情况,那么已经有一个JSON提供程序在幕后自动注册,那么你就不需要注册另一个了。