web-dev-qa-db-fra.com

Définir le fuseau horaire de Jackson pour la désérialisation de la date

J'utilise Jackson (via Spring MVC Annotations) pour désérialiser un champ en un Java.util.Date à partir de JSON. Le POST ressemble à - {"enrollDate":"2011-09-28T00:00:00.000Z"}, mais lorsque l’objet est créé par Spring & Jackson, il définit la date sur "2011-09-27 20:00:00"

Comment puis-je définir le fuseau horaire approprié à Jackson? Ou si ce n'est pas le problème, comment puis-je envoyer EST à partir du message JSON?  

Javascript/jQuery:

var personDataView = { enrollDate : new Date($("#enrollDate").val()), 
                       //...other members
                      };


$.postJSON('/some/path/', personDataView, function(data){
    //... handle the response here

});

Message JSON:

{"enrollDate":"2011-09-28T00:00:00.000Z"}

Contrôleur à ressort:

@RequestMapping(value="/", method=RequestMethod.POST)
public @ResponseBody String saveProfile(@RequestBody personDataView persondataView, HttpServletRequest request)
{
        //...dataView has a Java.util.Date enrollDate field
        //...other code
}
33
Mike G

Dans Jackson 2+, vous pouvez également utiliser l'annotation @JsonFormat:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone="America/Phoenix")
private Date date;
31
Olivier Lecrivain

Si vous voulez vraiment que Jackson renvoie une date avec un fuseau horaire autre que UTC (et que j'ai moi-même plusieurs arguments valables, notamment lorsque certains clients ne comprennent pas le fuseau horaire), je le fais généralement:

ObjectMapper mapper = new ObjectMapper();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
dateFormat.setTimeZone(TimeZone.getTimeZone("CET"));
mapper.getSerializationConfig().setDateFormat(dateFormat);
// ... etc

Il n’a aucun effet négatif sur ceux qui comprennent le fuseau horaire-p

15
SiCN

J'utilise Jackson 1.9.7 et j'ai constaté que ce qui suit ne résout pas le problème de fuseau horaire relatif à la sérialisation/désérialisation:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
objectMapper.setDateFormat(dateFormat);

Au lieu de "2014-02-13T20: 09: 09.859Z", le message JSON contient "2014-02-13T08: 09: 09.859 + 0000", ce qui est évidemment incorrect. Je n'ai pas le temps de parcourir le code source de la bibliothèque Jackson pour comprendre pourquoi cela se produit. Cependant, j'ai constaté que si je spécifie simplement la classe ISO8601DateFormat fournie par Jackson à la méthode ObjectMapper.setDateFormat, la date est correcte.

Sauf que cela ne met pas les millisecondes dans le format que je veux, alors j'ai sous-classé la classe ISO8601DateFormat et remplacé la format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) méthode. 

/**
 * Provides a ISO8601 date format implementation that includes milliseconds
 *
 */
public class ISO8601DateFormatWithMillis extends ISO8601DateFormat {

  /**
   * For serialization
   */
  private static final long serialVersionUID = 2672976499021731672L;


  @Override
  public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition)
  {
      String value = ISO8601Utils.format(date, true);
      toAppendTo.append(value);
      return toAppendTo;
  }
}
4
whitestryder

Avez-vous essayé cela dans votre application.properties?

spring.jackson.time-zone= # Time zone used when formatting dates. For instance `America/Los_Angeles`
2
QFY

Votre objet de date est probablement correct, car vous avez envoyé votre date codée au format ISO avec le fuseau horaire GMT et vous êtes en mode EST lorsque vous imprimez votre date. 

Notez que les objets Date effectuent la conversion du fuseau horaire au moment où ils sont imprimés . Vous pouvez vérifier si votre objet date est correct avec:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTime(date);
System.out.println (cal);
1
jjmontes

J'ai eu le même problème avec la désérialisation du calendrier, résolu en étendant CalendarDeserializer. 
Il force le fuseau horaire UTC
Je colle le code si quelqu'un en a besoin:

@JacksonStdImpl
public class UtcCalendarDeserializer extends CalendarDeserializer {

    TimeZone TZ_UTC = TimeZone.getTimeZone("UTC");

    @Override
    public Calendar deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonToken t = jp.getCurrentToken();
        if (t == JsonToken.VALUE_NUMBER_INT) {
            Calendar cal = Calendar.getInstance(TZ_UTC);
            cal.clear();
            cal.setTimeInMillis(jp.getLongValue());

            return cal;
        }

        return super.deserialize(jp, ctxt);
    }
}

dans la classe de modèle JSON, il suffit d'annoter le champ avec:

@JsonDeserialize(using = UtcCalendarDeserializer.class)
private Calendar myCalendar;
1
fl4l

Vient juste d’entrer dans cette affaire et a finalement réalisé que LocalDateTime n’a aucune information de fuseau horaire. Si vous avez reçu une chaîne de date avec des informations sur le fuseau horaire, vous devez l’utiliser comme type:

ZonedDateTime

Cochez cette link

0
Lichader