126 votes

Comment sérialiser Joda DateTime avec le processeur Jackson JSON ?

Comment faire pour que Jackson sérialise mon objet Joda DateTime selon un modèle simple (comme "dd-MM-yyyy") ?

J'ai essayé :

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

J'ai aussi essayé :

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

Merci !

0 votes

Les deux éléments ci-dessus devraient également fonctionner (@JsonSerialize devrait impliquer que le champ doit être sérialisé ; et le format de date devrait également s'appliquer idéalement à Joda). jira.codehaus.org/browse/JACKSON .

0 votes

Je réalise que cette question date d'il y a un certain temps, mais pour référence future, objectMapper.getSerializationConfig().setDateFormat(df) est maintenant déprécié. objectMapper.setDateFormat(df) est maintenant suggéré.

0 votes

154voto

Kimble Points 2114

Cela est devenu très facile avec Jackson 2.0 et le module Joda.

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

Dépendance Maven :

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

Code et documentation : https://github.com/FasterXML/jackson-datatype-joda

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

17 votes

Pouvez-vous nous en dire plus ? Où va ce code et comment est utilisée l'instance d'ObjectMapper ?

0 votes

Vous devez poser des questions spécifiques concernant l'utilisation de l'api de Jackson et de Maven. L'emplacement du code dépend de l'utilisation ou non de frameworks et de la façon dont vous démarrez votre application.

4 votes

Lorsque je l'ajoute, j'obtiens l'erreur de compilation "incompatible types : JodaModule cannot be converted to Module" - la méthode attend un org.codehaus.jackson.map.Module mais JodaModule n'en a pas dans son héritière donc comment cela peut-il fonctionner ?

74voto

Rusty Kuntz Points 441

Dans l'objet que vous mappez :

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

Dans 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 votes

Comment enregistrer CustomDateSerializer dans spring mvc 3 ?

1 votes

Je ne connais pas Spring MVC3, mais vous pouvez ajouter un serializer personnalisé à l'objet mapper Jackson. Voir cette entrée dans Jackson Vous devez créer un module simple pour cela SimpleModule isoDateTimeModule = new SimpleModule("ISODateTimeModule", new Version(1, 0, 0, null)) ; isoDateTimeModule.addSerializer(new JsonISODateTimeFormatSerializer()) ; mapper.registerModule(isoDateTimeModule) ;

1 votes

@digz6666 voir ma réponse ici pour Spring MVC 3 : stackoverflow.com/questions/7854030/

27voto

oggmonster Points 751

Comme l'a dit @Kimble, avec Jackson 2, l'utilisation du formatage par défaut est très simple ; il suffit d'enregistrer JodaModule sur votre ObjectMapper .

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

Pour la sérialisation/dé-sérialisation personnalisée de DateTime vous devez mettre en œuvre votre propre StdScalarSerializer y StdScalarDeserializer ; c'est assez alambiqué, mais peu importe.

Par exemple, voici un DateTime sérialiseur qui utilise le ISODateFormat avec le fuseau horaire 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);
    }
}

Et le dé-sérialiseur correspondant :

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

Puis, vous les reliez entre eux par un module :

public class DateTimeModule extends SimpleModule {

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

Ensuite, enregistrez le module sur votre ObjectMapper :

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

0 votes

L'objet DatatIme déserté est dans le fuseau horaire UTC ou bien dans le fuseau horaire des navigateurs s'il vous plaît aidez-moi

0 votes

Est-ce que cela enregistre le mappeur (et les modules) de manière globale ?

16voto

Moesio Points 788

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

Bien que vous puissiez mettre une annotation pour chaque champ de date, il est préférable de faire une configuration globale pour votre mappeur d'objets. Si vous utilisez jackson, vous pouvez configurer votre spring comme suit :

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

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

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

Bien entendu, SimpleDateFormat peut utiliser le format de votre choix.

4 votes

setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz")); a fait l'affaire pour moi, thx

3voto

ydrozhdzhal Points 51

Il semble que pour Jackson 1.9.12 il n'y ait pas cette possibilité par défaut, à cause de :

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

Cette classe sérialise les données en utilisant la méthode toString() de Joda DateTime.

L'approche proposée par Rusty Kuntz fonctionne parfaitement dans mon cas.

0 votes

Vous pouvez toujours enregistrer un sérialiseur et un désérialiseur personnalisés, et ceux-ci auront la priorité sur la mise en œuvre par défaut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X