【发布时间】:2017-11-09 23:53:52
【问题描述】:
我从 Spring Boot 应用程序调用 web 服务,使用 jackson-jsr-310 作为 maven 依赖项,以便能够使用 LocalDateTime:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders httpHeaders = this.createHeaders();
ResponseEntity<String> response;
response = restTemplate.exchange(uri,HttpMethod.GET,new HttpEntity<Object>(httpHeaders),String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
BusinessPartner test = mapper.readValue(response.getBody(), BusinessPartner.class);
我的问题在最后一行,代码产生了这个错误:
java.time.format.DateTimeParseException:无法在索引 0 处解析文本“/Date(591321600000)/”
response.getBody() 中生成的 JSON 如下所示:
{
"d":{
...
"Address":{...},
"FirstName":"asd",
"LastName":"asd",
"BirthDate":"\/Date(591321600000)\/",
}
}
在我的模型类中,我有以下成员:
@JsonProperty("BirthDate")
private LocalDateTime birthDate;
所以,在这里搜索了一下后,我发现/Date(...)/ 似乎是 Microsoft 专有的日期格式,Jackson 默认无法将其反序列化为对象。
一些问题建议创建一个自定义 SimpleDateFormat 并将其应用于我尝试做的 opbject 映射器,但后来我想我错过了 mapper.setDateFormat(new SimpleDateFormat("...")); 的正确语法
我试过用例如mapper.setDateFormat(new SimpleDateFormat("/Date(S)/"));
或者最后甚至mapper.setDateFormat(new SimpleDateFormat("SSSSSSSSSSSS)"));
但这似乎也不起作用,所以我现在没有想法,希望这里的一些人可以帮助我。
编辑 1:
进一步调查,似乎一种方法是为杰克逊编写自定义DateDeSerializer。所以我尝试了这个:
@Component
public class JsonDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
private DateTimeFormatter formatter;
private JsonDateTimeDeserializer() {
this(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
public JsonDateTimeDeserializer(DateTimeFormatter formatter) {
this.formatter = formatter;
}
@Override
public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException
{
if (parser.hasTokenId(JsonTokenId.ID_STRING)) {
String unixEpochString = parser.getText().trim();
unixEpochString = unixEpochString.replaceAll("[^\\d.]", "");
long unixTime = Long.valueOf(unixEpochString);
if (unixEpochString.length() == 0) {
return null;
}
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(unixTime), ZoneId.systemDefault());
localDateTime.format(formatter);
return localDateTime;
}
return null;
}
}
实际上几乎返回了我想要的,使用
在模型中注释我的字段@JsonDeserialize(using = JsonDateTimeDeserializer.class)
但不完全是:
此代码返回 LocalDateTime 值:1988-09-27T01:00。
但在第三方系统中,xml值为1988-09-27T00:00:00。
很明显,这里的ZoneId:
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(unixTime), ZoneId.systemDefault());
是问题所在,除了日期格式错误。
那么这里有人可以帮我解决如何切换到time-part 始终使用零并让我的日期格式正确吗?会很棒!
【问题讨论】:
-
591321600000是纪元毫秒(从 1970-01-01T00:00:00Z 开始的毫秒数)? -
@Hugo 是的,是的。请查看我的编辑以获取更多信息。
-
System.out.println(ZoneId.systemDefault())的输出是什么? -
这是欧洲/柏林(这里下雨),偏移量为 +01:00,这就是为什么我说问题出在哪里很明显。没想到来自圣保罗的人 ;)
标签: datetime spring-boot java-8 jackson deserialization