Kev*_*ave 133 java json date pojo jackson
我有一个来自API的日期格式,如下所示:
"start_time": "2015-10-1 3:00 PM GMT+1:00"
Run Code Online (Sandbox Code Playgroud)
这是YYYY-DD-MM HH:MM am/pm GMT时间戳.我将此值映射到POJO中的Date变量.显然,它显示转换错误.
我想知道两件事:
Oli*_*ain 300
从Jackson v2.0开始,你可以直接在Object成员上使用@JsonFormat注释;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm a z")
private Date date;
Run Code Online (Sandbox Code Playgroud)
pb2*_*b2q 113
我需要使用什么格式来与杰克逊进行转换?Date是一个很好的字段类型吗?
Date这是一个很好的领域类型.您可以使用ObjectMapper.setDateFormat以下命令轻松地使JSON解析:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
myObjectMapper.setDateFormat(df);
Run Code Online (Sandbox Code Playgroud)
通常,有没有办法在变量被Jackson映射到Object成员之前处理变量?比如,更改格式,计算等.
是.您有几个选项,包括实现自定义JsonDeserializer,例如扩展JsonDeserializer<Date>.这是一个好的开始.
Mik*_*van 46
当然,有一种称为序列化和反序列化的自动方式,您可以使用pb2q提到的特定注释(@JsonSerialize,@ JsonDeserialize)来定义它.
您可以同时使用java.util.Date和java.util.Calendar ...以及JodaTime.
在反序列化过程中,@ JsonFormat注释对我不起作用(它已将时区调整为不同的值)(序列化工作完美):
@JsonFormat(locale = "hu", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "CET")
@JsonFormat(locale = "hu", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "Europe/Budapest")
Run Code Online (Sandbox Code Playgroud)
如果需要预测结果,则需要使用自定义序列化器和自定义反序列化器而不是@JsonFormat注释.我在http://www.baeldung.com/jackson-serialize-dates找到了真正好的教程和解决方案
日期字段有一些示例,但我需要日历字段,所以这是我的实现:
该串行器类:
public class CustomCalendarSerializer extends JsonSerializer<Calendar> {
public static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
public static final Locale LOCALE_HUNGARIAN = new Locale("hu", "HU");
public static final TimeZone LOCAL_TIME_ZONE = TimeZone.getTimeZone("Europe/Budapest");
@Override
public void serialize(Calendar value, JsonGenerator gen, SerializerProvider arg2)
throws IOException, JsonProcessingException {
if (value == null) {
gen.writeNull();
} else {
gen.writeString(FORMATTER.format(value.getTime()));
}
}
}
Run Code Online (Sandbox Code Playgroud)
该解串器类:
public class CustomCalendarDeserializer extends JsonDeserializer<Calendar> {
@Override
public Calendar deserialize(JsonParser jsonparser, DeserializationContext context)
throws IOException, JsonProcessingException {
String dateAsString = jsonparser.getText();
try {
Date date = CustomCalendarSerializer.FORMATTER.parse(dateAsString);
Calendar calendar = Calendar.getInstance(
CustomCalendarSerializer.LOCAL_TIME_ZONE,
CustomCalendarSerializer.LOCALE_HUNGARIAN
);
calendar.setTime(date);
return calendar;
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
以及上述类的用法:
public class CalendarEntry {
@JsonSerialize(using = CustomCalendarSerializer.class)
@JsonDeserialize(using = CustomCalendarDeserializer.class)
private Calendar calendar;
// ... additional things ...
}
Run Code Online (Sandbox Code Playgroud)
使用此实现,序列化和反序列化过程的执行连续产生原始值.
仅使用@JsonFormat注释反序列化提供了不同的结果,我想是因为图书馆内部时区缺省的设置你不能标注参数的变化(这是我与杰克逊库2.5.3和2.6.3版本的经验,以及).
在您的日期中添加诸如 T 和 Z 之类的字符
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private Date currentTime;
Run Code Online (Sandbox Code Playgroud)
输出
{
"currentTime": "2019-12-11T11:40:49Z"
}
Run Code Online (Sandbox Code Playgroud)
只是具有日期时间格式的Spring Boot应用程序的完整示例RFC3339
package bj.demo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import java.text.SimpleDateFormat;
/**
* Created by BaiJiFeiLong@gmail.com at 2018/5/4 10:22
*/
@SpringBootApplication
public class BarApp implements ApplicationListener<ApplicationReadyEvent> {
public static void main(String[] args) {
SpringApplication.run(BarApp.class, args);
}
@Autowired
private ObjectMapper objectMapper;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
}
}
Run Code Online (Sandbox Code Playgroud)
基于 @miklov-kriven 非常有用的答案,我希望这两个额外的考虑点对某人有所帮助:
(1) 我发现将序列化器和反序列化器作为静态内部类包含在同一个类中是一个好主意。注意,使用 ThreadLocal 来保证 SimpleDateFormat 的线程安全。
public class DateConverter {
private static final ThreadLocal<SimpleDateFormat> sdf =
ThreadLocal.<SimpleDateFormat>withInitial(
() -> {return new SimpleDateFormat("yyyy-MM-dd HH:mm a z");});
public static class Serialize extends JsonSerializer<Date> {
@Override
public void serialize(Date value, JsonGenerator jgen SerializerProvider provider) throws Exception {
if (value == null) {
jgen.writeNull();
}
else {
jgen.writeString(sdf.get().format(value));
}
}
}
public static class Deserialize extends JsonDeserializer<Date> {
@Overrride
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws Exception {
String dateAsString = jp.getText();
try {
if (Strings.isNullOrEmpty(dateAsString)) {
return null;
}
else {
return new Date(sdf.get().parse(dateAsString).getTime());
}
}
catch (ParseException pe) {
throw new RuntimeException(pe);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
(2) 作为在每个单独的类成员上使用 @JsonSerialize 和 @JsonDeserialize 注释的替代方法,您还可以考虑通过在应用程序级别应用自定义序列化来覆盖 Jackson 的默认序列化,即所有 Date 类型的类成员都将由 Jackson 序列化使用此自定义序列化,而无需在每个字段上显式注释。例如,如果您使用 Spring Boot,执行此操作的一种方法如下:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Module customModule() {
SimpleModule module = new SimpleModule();
module.addSerializer(Date.class, new DateConverter.Serialize());
module.addDeserializer(Date.class, new Dateconverter.Deserialize());
return module;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
345145 次 |
| 最近记录: |