Как сериализовать Joda DateTime с процессором Jackson JSON? - PullRequest
114 голосов
/ 17 июля 2010

Как мне заставить Джексона сериализовать мой объект Joda DateTime в соответствии с простым шаблоном (например, "dd-MM-yyyy")?

Я пробовал:

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

Я также пробовал:

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

Спасибо!

Ответы [ 9 ]

137 голосов
/ 25 марта 2013

Это стало очень легко с 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/

74 голосов
/ 17 июля 2010

В отображаемом объекте:

@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));
    }
}
22 голосов
/ 16 сентября 2014

Как сказал @Kimble, в Jackson 2 использовать форматирование по умолчанию очень просто;просто зарегистрируйте JodaModule на вашем ObjectMapper.

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

Для настраиваемой сериализации / десериализации DateTime вам необходимо реализовать свои собственные StdScalarSerializer и StdScalarDeserializer;это довольно запутанно, но все равно.

Например, вот сериализатор DateTime, который использует ISODateFormat с часовым поясом UTC:

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());
15 голосов
/ 24 июля 2015

Простое решение

Я столкнулся с подобной проблемой, и мое решение гораздо яснее, чем выше.

Я просто использовал шаблон в @JsonFormat аннотация

В основном у моего класса есть поле DateTime, поэтому я помещаю аннотацию вокруг геттера:

@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 голосов
/ 31 мая 2012

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 может использовать любой формат, который вам нужен.

7 голосов
/ 28 марта 2017

Тем временем Джексон автоматически регистрирует модуль Joda, когда JodaModule находится в classpath.Я просто добавил Джексон-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"}
4 голосов
/ 19 ноября 2016

Для тех, кто использует Spring Boot, вам нужно добавить модуль в ваш контекст, и он будет добавлен в вашу конфигурацию следующим образом.

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

А если вы хотите использовать новый модуль времени java8 jsr-310.

@Bean
public Module jodaTimeModule() {
    return new JavaTimeModule();
}
3 голосов
/ 08 апреля 2013

Похоже, что для 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);
    }
}

Этот класс сериализует данные, используя метод toString () Joda DateTime.

Подход, предложенный Расти Кунцем, отлично подходит для моего случая.

2 голосов
/ 14 декабря 2016

Я использую 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());

...