web-dev-qa-db-ja.com

日付の逆シリアル化にジャクソンのタイムゾーンを設定

私はJackson(Spring MVC Annotations経由)を使用してフィールドをJSONからJava.util.Dateにデシリアライズします。 POSTは-{"enrollDate":"2011-09-28T00:00:00.000Z"}のように見えますが、オブジェクトがSpring&Jacksonによって作成されると、日付は"2011-09-27 20:00:00"として設定されます。

ジャクソンで適切なタイムゾーンを設定するにはどうすればよいですか?またはそれが問題でない場合、JSONメッセージからESTを送信するにはどうすればよいですか?

Javascript/jQuery:

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


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

});

JSONメッセージ:

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

スプリングコントローラー:

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

Jackson 2+では、@ JsonFormatアノテーションも使用できます。

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

あなたが本当にジャクソンにUTC以外のタイムゾーンで日付を返したい場合(そして私自身は特にいくつかのクライアントがタイムゾーン部分を取得していないとき、それについていくつかの良い議論を持っています)、私は通常行います:

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

Timezone-pを理解している人には悪影響はありません

15
SiCN

Application.propertiesでこれを試しましたか?

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

私はジャクソン1.9.7を使用していますが、以下を実行しても、シリアル化/逆シリアル化のタイムゾーンの問題が解決しないことがわかりました。

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

「2014-02-13T20:09:09.859Z」の代わりに、JSONメッセージに「2014-02-13T08:09:09.859 + 0000」が表示されますが、これは明らかに正しくありません。ジャクソンライブラリのソースコードをステップ実行してこの問題が発生する理由を把握する時間はありませんが、ジャクソンが提供する_ISO8601DateFormat_クラスを_ObjectMapper.setDateFormat_メソッドに指定するだけで日付が正しいことがわかりました。

ただし、これはミリ秒を希望する形式に変換しないので、_ISO8601DateFormat_クラスをサブクラス化し、format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition)メソッドをオーバーライドしました。

_/**
 * 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

ISO形式でエンコードされた日付をGMTタイムゾーンで送信し、日付を印刷するときにESTにいるため、日付オブジェクトはおそらく大丈夫です。

Dateオブジェクトは、printedの時点でタイムゾーン変換を実行することに注意してください。 dateオブジェクトが正しいかどうかを確認するには:

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

この問題が発生し、ようやくLocalDateTimeにタイムゾーン情報がないことがわかりました。タイムゾーン情報を含む日付文字列を受け取った場合、これをタイプとして使用する必要があります。

ZonedDateTime

これを確認してください link

1
Lichader

Calendar Deserializationで同じ問題が発生し、CalendarDeserializerの拡張を解決しました。
UTCタイムゾーンを強制します
コードが必要な場合は貼り付けます:

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

jSONモデルクラスでは、次のようにフィールドに注釈を付けるだけです。

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