如何使用Jackson JSON处理器序列化Joda DateTime?


118

如何让Jackson根据一种简单的模式(例如“ dd-MM-yyyy”)序列化我的Joda DateTime对象?

我试过了:

@JsonSerialize(using=DateTimeSerializer.class)
private final DateTime date;

我也尝试过:

ObjectMapper mapper = new ObjectMapper()
    .getSerializationConfig()
    .setDateFormat(df);

谢谢!


以上两种方法实际上都应该可行(@JsonSerialize应该暗示要对该字段进行序列化;日期格式也应该适用于Joda),因此您可能想在jira.codehaus.org/browse/JACKSON中提交一个Jira错误。
StaxMan 2010年

我意识到这个问题是有一段时间了,但是为了将来参考,现在不推荐使用objectMapper.getSerializationConfig()。setDateFormat(df)。现在建议使用objectMapper.setDateFormat(df)。
Patrick

Answers:


146

使用Jackson 2.0和Joda模块,这变得非常容易。

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());

Maven依赖项:

<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-joda</artifactId>
  <version>2.1.1</version>
</dependency>  

代码和文档:https : //github.com/FasterXML/jackson-datatype-joda

二进制文件:http : //repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-joda/


13
您能对此进行扩展吗?这段代码在哪里,如何使用ObjectMapper实例?
保罗

您应该询问有关使用Jackson的api和Maven的特定问题。代码的去向取决于您是否使用任何框架/如何引导应用程序。
Kimble 2013年

4
当我补充说我收到编译错误“不兼容的类型:JodaModule无法转换为Module”时,该方法需要org.codehaus.jackson.map.Module,但是JodaModule的继承体系中没有此功能,那么这怎么工作?
马丁·查尔斯沃思

4
很有希望,但目前几乎没有用,因为我们无法指定要解析的日期格式:(
Vincent Mimoun-Prat 2014年

10
您需要禁用序列化作为时间戳objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
MarekM 2014年

74

在您要映射的对象中:

@JsonSerialize(using = CustomDateSerializer.class)
public DateTime getDate() { ... }

在CustomDateSerializer中:

public class CustomDateSerializer extends JsonSerializer<DateTime> {

    private static DateTimeFormatter formatter = 
        DateTimeFormat.forPattern("dd-MM-yyyy");

    @Override
    public void serialize(DateTime value, JsonGenerator gen, 
                          SerializerProvider arg2)
        throws IOException, JsonProcessingException {

        gen.writeString(formatter.print(value));
    }
}

4
如何在Spring MVC 3中注册CustomDateSerializer?
digz6666 2011年

1
我不了解Spring MVC3,但是您可以向Jackson映射器对象添加自定义序列化器。请在Jackson中查看此条目。您需要为该SimpleModule创建一个简单模块isoDateTimeModule = new SimpleModule(“ ISODateTimeModule”,new Version(1,0,0,null)); isoDateTimeModule.addSerializer(new JsonISODateTimeFormatSerializer()); mapper.registerModule(isoDateTimeModule);
Guillaume Belrose

1
@ digz6666在这里看到我的回答对Spring MVC 3:stackoverflow.com/questions/7854030/...
亚兰·科恰良

注意-确保使用org.codehaus.jackson而不是中的上述类com.fasterxml.jackson.core。使用第二个软件包对我不起作用。实际上,我的Jersey应用程序甚至都没有遵守@JsonSerialized注释。
凯文·梅雷迪斯

答案确实对我有用。但这将在所有字段上都需要此注释。为此,是否有一些适用于Jackson的全局配置?
塔赫2015年

26

正如@Kimble所说,对于Jackson 2,使用默认格式非常容易;只需JodaModule在您的上注册即可ObjectMapper

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());

对于的自定义序列化/反序列化DateTime,您需要实现自己的StdScalarSerializerStdScalarDeserializer; 它非常令人费解,但是无论如何。

例如,这是一个在UTC时区DateTime使用的序列化器ISODateFormat

public class DateTimeSerializer extends StdScalarSerializer<DateTime> {

    public DateTimeSerializer() {
        super(DateTime.class);
    }

    @Override
    public void serialize(DateTime dateTime,
                          JsonGenerator jsonGenerator,
                          SerializerProvider provider) throws IOException, JsonGenerationException {
        String dateTimeAsString = ISODateTimeFormat.withZoneUTC().print(dateTime);
        jsonGenerator.writeString(dateTimeAsString);
    }
}

以及相应的反序列化器:

public class DateTimeDesrializer extends StdScalarDeserializer<DateTime> {

    public DateTimeDesrializer() {
        super(DateTime.class);
    }

    @Override
    public DateTime deserialize(JsonParser jsonParser,
                                DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        try {
            JsonToken currentToken = jsonParser.getCurrentToken();
            if (currentToken == JsonToken.VALUE_STRING) {
                String dateTimeAsString = jsonParser.getText().trim();
                return ISODateTimeFormat.withZoneUTC().parseDateTime(dateTimeAsString);
            }
        } finally {
            throw deserializationContext.mappingException(getValueClass());
        }
    }

然后将这些与模块捆绑在一起:

public class DateTimeModule extends SimpleModule {

    public DateTimeModule() {
        super();
        addSerializer(DateTime.class, new DateTimeSerializer());
        addDeserializer(DateTime.class, new DateTimeDeserializer());
    }
}

然后在您的上注册该模块ObjectMapper

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new DateTimeModule());

已反序列化的DatatIme对象位于UTC时区,否则浏览器的时区请帮助我
user3354457 2015年

这会在全局注册映射器(和模块)吗?
拉菲安

16

简单的解决方案

我遇到了类似的问题,我的解决方案比上面的要清楚得多。

我只是在 注解中使用了模式@JsonFormat

基本上我的课有一个DateTime字段,所以我在getter周围添加了一个注释:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public DateTime getDate() {
    return date;
}

我用 ObjectMapper

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JodaModule());
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    ObjectWriter ow = mapper.writer();
    try {
        String logStr = ow.writeValueAsString(log);
        outLogger.info(logStr);
    } catch (IOException e) {
        logger.warn("JSON mapping exception", e);
    }

我们使用杰克逊2.5.4


15

https://stackoverflow.com/a/10835114/1113510

尽管可以为每个日期字段添加注释,但是最好为对象映射器进行全局配置。如果使用杰克逊,则可以按以下方式配置弹簧:

<bean id="jacksonObjectMapper" class="com.company.CustomObjectMapper" />

<bean id="jacksonSerializationConfig" class="org.codehaus.jackson.map.SerializationConfig"
    factory-bean="jacksonObjectMapper" factory-method="getSerializationConfig" >
</bean>

对于CustomObjectMapper:

public class CustomObjectMapper extends ObjectMapper {

    public CustomObjectMapper() {
        super();
        configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
        setDateFormat(new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'ZZZ (z)"));
    }
}

当然,SimpleDateFormat可以使用您需要的任何格式。


4
setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"));为我做了把戏,谢谢
Konsumierer 2012年

8

同时,当JodaModule在类路径中时,Jackson自动注册Joda模块。我刚刚将jackson-datatype-joda添加到Maven,它立即起作用。

<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-joda</artifactId>
  <version>2.8.7</version>
</dependency>

JSON输出:

{"created" : "2017-03-28T05:59:27.258Z"}

6

对于使用Spring Boot的用户,您必须将模块添加到上下文中,并且它将像这样添加到您的配置中。

@Bean
public Module jodaTimeModule() {
    return new JodaModule();
}

如果要使用新的java8时间模块jsr-310。

@Bean
public Module jodaTimeModule() {
    return new JavaTimeModule();
}

3

似乎对于Jackson 1.9.12,默认情况下没有这种可能性,原因是:

public final static class DateTimeSerializer
    extends JodaSerializer<DateTime>
{
    public DateTimeSerializer() { super(DateTime.class); }

    @Override
    public void serialize(DateTime value, JsonGenerator jgen, SerializerProvider provider)
        throws IOException, JsonGenerationException
    {
        if (provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)) {
            jgen.writeNumber(value.getMillis());
        } else {
            jgen.writeString(value.toString());
        }
    }

    @Override
    public JsonNode getSchema(SerializerProvider provider, java.lang.reflect.Type typeHint)
    {
        return createSchemaNode(provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)
                ? "number" : "string", true);
    }
}

此类使用Joda DateTime的toString()方法序列化数据。

Rusty Kuntz提出的方法非常适合我的情况。


您仍然可以注册自定义序列化器和反序列化器,并且它们将优先于默认实现。
StaxMan

2

我正在使用Java 8,这对我有用。

添加对 pom.xml

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.4.0</version>
</dependency>

并在您的计算机上添加JodaModule ObjectMapper

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.