9

Jackson と java.util.Date コードの間の多くの例がありますが、それらはすべて POJO アノテーションを利用しているようです。JSON にデシリアライズしたいスカラーの一般的なマップがあります。これが現在のデシリアライザーのセットアップです。非常に簡単です:

public class JSONUtils {
    static {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

        mapper = new ObjectMapper();

        mapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
        mapper.setDateFormat(df);  // this works for outbounds but has no effect on inbounds

        mapper.getDeserializationConfig().with(df); // Gave this a shot but still does not sniff strings for a format that we declare should be treated as java.util.Date                           
  }
  public static Map<String,Object> parseJSON(InputStream is) {
    Map<String,Object> data = null;

    try {
        data = mapper.readValue(is, Map.class);
    } catch(Exception e) {
      // ...
    }

    return data;
}

私は、dateserializer が java.util.Date を ISO 8601 っぽい文字列に変換できることを理解しています。私を困惑させるのは別の方法です。明らかに、コンテキストのない JSON ドキュメントでは、文字列は文字列であるため、それがかつて日付であったかどうかはわかりません。だから私はこれをダックタイプして、デシリアライズされているすべての文字列を調べる準備ができています.YYYY-MM-DDTHH:MM:SS.sssの日付時刻のような匂いがする場合は、文字列を返すだけでなく、java.util.Dateを作成します。与えられた:

{ "name": "buzz",
  "theDate": "2013-09-10T12:00:00.000"
}

譲ります

Map<String,Object> m = mapper.readValue(is, Map.class);
Object o1 = m.get("name");   // o1 is instanceof String
Object o2 = m.get("theDate");  // o2 is instanceof Date

しかし、これは、デシリアライザーが 2 つの異なる型を返さなければならないことを意味し、Jackson でこれを行う方法を理解できませんでした。日付のような文字列を盗聴し、それらを日付に変換し、他のものを文字列として残す、適切でコンパクトな例を知っている人はいますか?

4

4 に答える 4

3

これを数週間調べた後(他のコメントや回答はありません)、私が求めていることはジャクソンでは不可能だと今では信じています。日付のダックタイピングを使用した JSON の Map への逆シリアル化は、事後に行う必要があります。解析ストリームを挿入したり、文字列を盗聴しYYYY-MM-DDTHH:MM:SS.SSSたり、一致したDateときに の代わりにオブジェクトを置換したりする方法はありませんString。Jackson に を構築させMapてから、Jackson の外でトップに戻って を歩き、Map日付を探る必要があります。

私が探している非常に具体的なアヒルがあるので、文字列を日付に変換する最速の実装は、カレンダーの適切な整数 mdyhms-ms を検証して設定する約 120 行の長さの手巻きのものです。を呼び出しますgetTime()。10,000,000 回の変換には 4240 ミリ秒、つまり約 2.3m/秒かかります。

ジョダタイムのロビーがパイプを鳴らす前に、はい、最初にそれを試しました:

// This is set up ONCE, outside the timing loop:
DateTimeFormatter format = ISODateTimeFormat.dateHourMinuteSecondMillis();

// These are in the timing loop:
while(loop) {
    DateTime time = format.parseDateTime("2013-09-09T14:45:00.123");
    Date d = time.toDate();
}

実行には約 9630 ミリ秒かかり、約 1.04m/秒です。半分の速さ。しかし、それは「すぐに使えるjavaxを使用する」オプションよりもはるかに高速です。

java.util.Calendar c2 = javax.xml.bind.DatatypeConverter.parseDateTime(s);
Date d = c2.getTime();

これを実行するには 30428 回のミルが必要で、約 0.33m/秒で、ハンドロールよりもほぼ 7 倍遅くなります。

SimpleDateFormatはスレッド セーフではないため、呼び出し元について想定できないコンバータ ユーティリティでの使用は考慮されませんでした。

于 2013-10-09T15:10:23.623 に答える