Joda DateTime'ı Jackson JSON işlemciyle nasıl serileştirebilirim?


118

Jackson'ın Joda DateTime nesnemi basit bir modele göre ("gg-MM-yyyy" gibi) serileştirmesini nasıl sağlayabilirim?

Denedim:

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

Ben de denedim:

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

Teşekkürler!


Yukarıdakilerin her ikisi de gerçekten çalışmalıdır (@JsonSerialize, bu alanın serileştirilmesi gerektiğini ima etmelidir; ve tarih formatı da ideal olarak Joda için geçerli olmalıdır), bu nedenle jira.codehaus.org/browse/JACKSON adresinde bir Jira hatası dosyalamak isteyebilirsiniz .
StaxMan

Bu sorunun bir süre önce olduğunu biliyorum, ancak ileride başvurmak için objectMapper.getSerializationConfig (). SetDateFormat (df) artık kullanımdan kaldırıldı. objectMapper.setDateFormat (df) artık önerilmektedir.
Patrick

Yanıtlar:


146

Bu, Jackson 2.0 ve Joda modülü ile çok kolay hale geldi.

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

Maven bağımlılığı:

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

Kod ve belgeler: https://github.com/FasterXML/jackson-datatype-joda

İkililer: http://repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-joda/


13
Bu konuyu biraz açabilir misin lütfen? Bu kod nereye gider ve ObjectMapper örneği nasıl kullanılır?
Paul

Jackson'ın api'si ve Maven'in kullanımıyla ilgili özel sorular sormalısınız. Kodun nereye gideceği, herhangi bir çerçeve kullanıp kullanmadığınıza / uygulamanızı nasıl önyüklediğinize bağlıdır.
Kimble

4
"uyumsuz türler: JodaModule Modüle dönüştürülemiyor" derleme hatasını aldığımı eklediğimde - yöntem bir org.codehaus.jackson.map.Module bekliyor, ancak JodaModule kendi mirasçısında buna sahip değil, peki bu nasıl çalışabilir?
Martin Charlesworth

4
Umut verici ama şu anda neredeyse işe yaramaz çünkü ayrıştırılacak tarih formatını belirleyemiyoruz :(
Vincent Mimoun-Prat

10
ObjectMapper.disable (SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) zaman damgaları olarak serileştirmeyi devre dışı bırakmanız gerekir;
MarekM

74

Eşleştirdiğiniz nesnede:

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

CustomDateSerializer'da:

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'te CustomDateSerializer nasıl kaydedilir?
digz6666

1
Spring MVC3'ü bilmiyorum, ancak Jackson mapper nesnesine özel bir serileştirici ekleyebilirsiniz. Jackson'daki bu girdiye bakın Bu SimpleModule için basit bir modül oluşturmanız gerekir isoDateTimeModule = new SimpleModule ("ISODateTimeModule", new Version (1, 0, 0, null)); isoDateTimeModule.addSerializer (yeni JsonISODateTimeFormatSerializer ()); mapper.registerModule (isoDateTimeModule);
Guillaume Belrose

1
@ digz6666 İlkbahar MVC 3 için cevabımı burada görün: stackoverflow.com/questions/7854030/…
Aram Kocharyan

Not - org.codehaus.jacksonyerine yukarıdaki sınıfları kullandığınızdan emin olun com.fasterxml.jackson.core. İkinci paketi kullanmak benim için işe yaramadı. Aslında, Jersey uygulamam @JsonSerializedek açıklamaya bile saygı duymadı .
Kevin Meredith

Cevap benim için işe yaradı. Ancak tüm alanlarda bu ek açıklamayı gerektirecektir. Bunun için Jackson ile çalışan bazı küresel konfigürasyon var mı?
Taher

26

@Kimble'ın dediği gibi, Jackson 2 ile varsayılan biçimlendirmeyi kullanmak çok kolay; basitçe kayıt JodaModuleAşağıdaki yerlerde de ObjectMapper.

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

Özel serileştirme / serileştirmenin kaldırılması için DateTime, kendi StdScalarSerializerve StdScalarDeserializer; oldukça kıvrımlı, ama neyse.

Örneğin , UTC saat dilimiyle birlikte DateTimekullanan bir serileştirici 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);
    }
}

Ve ilgili serileştirici:

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());
        }
    }

Sonra bunları bir modülle birbirine bağlayın:

public class DateTimeModule extends SimpleModule {

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

Ardından modülü şuraya kaydedin ObjectMapper:

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

deserilazed DatatIme nesnesi UTC saat diliminde veya tarayıcıların saat diliminde lütfen bana yardım edin
user3354457

Bu, eşleyiciyi (ve modülleri) global olarak kaydeder mi?
raffian

16

Kolay çözüm

Benzer bir sorunla karşılaştım ve çözümüm yukarıdakinden çok açık.

Sadece kalıbı kullandım @JsonFormat ek açıklamada kullandım

Temelde sınıfımın bir DateTime alanı var, bu yüzden alıcıya bir açıklama koyuyorum:

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

Sınıfı serileştiriyorum 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);
    }

Jackson 2.5.4 kullanıyoruz


15

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

Her tarih alanı için bir açıklama koyabilseniz de, nesne eşleştiriciniz için genel bir yapılandırma yapmak daha iyidir. Jackson kullanıyorsanız, yayınızı aşağıdaki gibi yapılandırabilirsiniz:

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

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

CustomObjectMapper için:

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)"));
    }
}

Elbette, SimpleDateFormat ihtiyacınız olan herhangi bir formatı kullanabilir.


4
setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"));benim için hile yaptı, thx
Konsumierer

8

Bu arada Jackson, JodaModule sınıf yolunda olduğunda Joda modülünü otomatik olarak kaydeder. Jackson-datatype-joda'yı Maven'e ekledim ve anında çalıştı.

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

JSON çıktısı:

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

6

Spring Boot'a sahip olanlar için modülü bağlamınıza eklemelisiniz ve bu şekilde konfigürasyonunuza eklenecektir.

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

Ve yeni java8 zaman modülü jsr-310'u kullanmak istiyorsanız.

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

3

Görünüşe göre Jackson 1.9.12 için varsayılan olarak böyle bir olasılık yoktur, çünkü:

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);
    }
}

Bu sınıf, Joda DateTime'ın toString () yöntemini kullanarak verileri serileştirir.

Rusty Kuntz tarafından önerilen yaklaşım benim durumum için mükemmel çalışıyor.


Yine de özel serileştirici ve seri kaldırıcı kaydedebilirsiniz ve bunlar varsayılan uygulamaya göre önceliğe sahip olacaktır.
StaxMan

2

Java 8 kullanıyorum ve bu benim için çalıştı.

Bağımlılığı ekleyin pom.xml

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

ve üzerine JodaModule ekleyin ObjectMapper

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.