5 回答
TA贡献1712条经验 获得超3个赞
我只能控制ObjectMapper. 是否有任何可能的配置可以使这项工作?
只要您对时间和时区的默认值感到满意,就可以使用自定义反序列化器解决它:
public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {
@Override
public ZonedDateTime deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext)
throws IOException {
LocalDate localDate = LocalDate.parse(
jsonParser.getText(),
DateTimeFormatter.ISO_LOCAL_DATE);
return localDate.atStartOfDay(ZoneOffset.UTC);
}
}
然后将其添加到模块并将模块注册到您的ObjectMapper实例:
SimpleModule module = new SimpleModule();
module.addDeserializer(ZonedDateTime.class, new ZonedDateTimeDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
如果将反序列化器添加到模块中不适合您(从某种意义上说,此配置将应用于其他ZonedDateTime实例),那么您可以依靠混合来定义反序列化器将应用于哪些字段。首先定义一个mix-in接口,如下图:
public interface MarkdownMixIn {
@JsonDeserialize(using = ZonedDateTimeDeserializer.class)
ZonedDateTime getDate();
}
然后将混合接口绑定到所需的类:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Markdown.class, MarkdownMixIn.class);
TA贡献1757条经验 获得超7个赞
问题:我想将日期从 json 解析为 java LocalDateTime/ZonedDateTime 对象。ZonedDateTimeSerializer 存在但 ZonedDateTimeDeserializer 不存在。因此,为什么我创建了一个自定义 ZonedDateTimeDeserializer。
public static final String ZONED_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSz";
@Getter
@Setter
@JsonSerialize(using = ZonedDateTimeSerializer.class)
@JsonDeserialize(using = ZonedDateTimeDeserializer.class) // Doesn't exist, So I created a custom ZonedDateDeserializer utility class.
@JsonFormat(pattern = ZONED_DATE_TIME_FORMAT)
@JsonProperty("lastUpdated")
private ZonedDateTime lastUpdated;
解决方案:我最终得到了更简单、更少的代码行。
用于反序列化ZonedDateTime的实用程序类:
/**
* Custom {@link ZonedDateTime} deserializer.
*
* @param jsonParser for extracting the date in {@link String} format.
* @param deserializationContext for the process of deserialization a single root-level value.
* @return {@link ZonedDateTime} object of the date.
* @throws IOException throws I/O exceptions.
*/
public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {
@Override
public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
return ZonedDateTime.parse(jsonParser.getText(), DateTimeFormatter.ofPattern(ZONED_DATE_TIME_FORMAT));
}
}
如果您改用LocalDateTime怎么办。在那种情况下,它甚至更容易,反序列化器和序列化器类都已经提供给我们了。不需要上面定义的自定义实用程序类:
@Getter
@Setter
@JsonSerialize(using = LocalDateSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern = ZONED_DATE_TIME_FORMAT) //Specify the format you want: "yyyy-MM-dd'T'HH:mm:ss.SSS"
@JsonProperty("created")
private LocalDateTime created;
关键词:json格式 localDateTime zonedDateTime
TA贡献1786条经验 获得超11个赞
不幸的是,默认情况下您不能反序列化为String Object格式ZonedDateTime。但是您可以通过两种方式克服这个问题。
方式01
ZonedDateTime将类型更改为LocalDate在您的类中键入POJO并将值作为字符串传递03-06-2012
方式02
但是如果您必须使用时区存储日期和时间,那么您必须执行以下方法来克服
步骤01
ZonedDateTime使用 DateTimeFormat创建反序列化类
public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {
@Override
public ZonedDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss z");
LocalDate localDate = LocalDate.parse(p.getText(),dateTimeFormatter);
return localDate.atStartOfDay(ZoneOffset.UTC);
}
}
步骤02
@JsonDeserialize在方法级别注释的支持下,您必须在 POJO 类中将反序列化类与受影响的字段一起使用。
@JsonDeserialize(using = ZonedDateTimeDeserializer.class)
private ZonedDateTime startDate;
步骤03
以 ZonedDateTimeDeserializer 类给出的上述格式将值作为字符串传递
"startDate" : "09-03-2003 10:15:00 Europe/Paris"
TA贡献1900条经验 获得超5个赞
遗憾的是,如果不将 POJO 的类型更改为 LocalDate,那将很困难。
我能想到的最接近的解决方案是为杰克逊写一个习惯JsonDeserializer
,这绝对不是那种事情的好习惯。
TA贡献1876条经验 获得超6个赞
您可以编写自己的反序列化器,如@cassiomolin答案中所示。但也有另一种选择。在堆栈跟踪中,我们有DeserializationContext.weirdStringException方法允许我们提供DeserializationProblemHandler处理奇怪字符串值的方法。请参阅以下示例:
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;
public class AppJson {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
// override default time zone if needed
mapper.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
mapper.registerModule(new JavaTimeModule());
mapper.addHandler(new DeserializationProblemHandler() {
@Override
public Object handleWeirdStringValue(DeserializationContext ctxt, Class<?> targetType,
String valueToConvert, String failureMsg) {
LocalDate date = LocalDate.parse(valueToConvert, DateTimeFormatter.ISO_DATE);
return date.atStartOfDay(ctxt.getTimeZone().toZoneId());
}
});
String json = "{\"startDate\": \"2019-07-25\"}";
Markdown markdown = mapper.readValue(json, Markdown.class);
System.out.println(markdown);
}
}
上面的代码打印:
Markdown{startDate=2019-07-25T00:00-07:00[America/Los_Angeles]}
添加回答
举报