2017-02-14 15 views
3

私はそうのような分野での要求からJSONオブジェクトをデシリアライズするために春のブートアプリで使用されているJavaクラスを持っている:可変長の分数秒で日付を逆シリアル化するJavaの日付パターン?

@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX", timezone = "UTC") 
Instant timestamp; 

"をデシリアライズするためにジャクソンV2.6.6 @JsonFormatアノテーションを使用していますJSONの「タイムスタンプ」フィールドに表示されます。

"2017-01-09T21:49:26.70Z"

問題がない:私は見ている何

は、値のようなものであるとき、ということです。値は以下のように、小数第二小数点以下の桁数の単一の番号が含まれ、4つ以上の持っている場合

しかし:

"2017-01-09T21:49:26.7Z" or "2017-01-09T21:49:26.7000Z"

それから私は、次のエラーが発生します:

Caused by: java.time.format.DateTimeParseException: Text '2017-01-09T21:49:26.7Z' could not be parsed at index 19 
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) ~[?:1.8.0_65] 
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777) ~[?:1.8.0_65] 
    at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:150) ~[jackson-datatype-jsr310-2.6.6.jar:2.6.6] 
    at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:45) ~[jackson-datatype-jsr310-2.6.6.jar:2.6.6] 
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520) ~[jackson-databind-2.6.6.jar:2.6.6] 
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101) ~[jackson-databind-2.6.6.jar:2.6.6] 
    at com.fasterxml.jackson.module.afterburner.deser.SuperSonicBeanDeserializer.deserialize(SuperSonicBeanDeserializer.java:156) ~[jackson-module-afterburner-2.6.6.jar:2.6.6] 
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736) ~[jackson-databind-2.6.6.jar:2.6.6] 
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2764) ~[jackson-databind-2.6.6.jar:2.6.6] 

何このパターンを修正して、受け入れられる小数点以下の小数点以下の桁数の点で柔軟にすることができますか? https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

しかし、オブジェクトマッパーを寛大なモードに設定する方法がわかりません。

+0

何も動作しない場合は、 'String'と読むことができ、正規表現を使用して解析することができます。 – Caner

答えて

0

私はあなたには、いくつかは、後に一定の、いくつかの解析関連のバグがあったのJava 8の以前のリリースでは、いくつかのjava.timeバグを打つことも疑うあなたのJava実装

だけの推測...

を更新Java 8のアップデートとJava 9で修正されたもの。

私は1.8.0_65と推測しています。エラーテキストの文字列は、Java 8 Update 65を参照しています。現在はOracle implementation is at Update 121です。

どのようなフォーマッタですか?

私は知らないJackson。私は彼らが何を正確に呼びかけるのだろうかと思っています。DateTimeFormatter私はあなたのエラー引用にその情報が表示されません。

パターンの定義を省略して、Jacksonのデフォルト動作を確認できますか?

RAMの16回のライブがMacOSのを実行しているとのMacBook Pro(網膜、15インチ、後期2013)上でJava 8のアップデート121でInstant.parseを呼び出すことによって、あなたの文字列を解析するとき、私はそのような問題を見ていないInstant.parse

で問題ありませんシエラ10.12.3とNetBeans 8.2。

System.out.println ("Java vendor: " + System.getProperty ("java.vendor")); 
System.out.println ("Java version: " + System.getProperty ("java.version")); 

List<String> strings = new ArrayList<>(); 
strings.add ("2017-01-09T21:49:26.7Z"); 
strings.add ("2017-01-09T21:49:26.70Z"); 
strings.add ("2017-01-09T21:49:26.700Z"); 
strings.add ("2017-01-09T21:49:26.7000Z"); 
strings.add ("2017-01-09T21:49:26.70000Z"); 

for (String string : strings) { 
    try { 
     Instant instant = Instant.parse (string); 
     System.out.println ("GOOD - string: " + string + " parsed: " + instant); 
    } catch (DateTimeParseException e) { 
     System.out.println ("ERROR - Failed to parse string: " + string); 
    } 
} 
System.out.println ("Done."); 

実行時。

Java vendor: Oracle Corporation 
Java version: 1.8.0_121 
GOOD - string: 2017-01-09T21:49:26.7Z parsed: 2017-01-09T21:49:26.700Z 
GOOD - string: 2017-01-09T21:49:26.70Z parsed: 2017-01-09T21:49:26.700Z 
GOOD - string: 2017-01-09T21:49:26.700Z parsed: 2017-01-09T21:49:26.700Z 
GOOD - string: 2017-01-09T21:49:26.7000Z parsed: 2017-01-09T21:49:26.700Z 
GOOD - string: 2017-01-09T21:49:26.70000Z parsed: 2017-01-09T21:49:26.700Z 

また、この同じcode run live at IdeOne.comをOracle実装のJava 8 Update 121を実行しても問題なく表示できます。あなたのDateTimeFormatter.ofPattern

問題は、私は同様にあなたの書式設定のパターンを試してみました。 .70.700では動作しますが、他のものは動作しません。

DateTimeFormatter f = DateTimeFormatter.ofPattern ("yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX" , Locale.US); 
for (String string : strings) { 
    try { 
     OffsetDateTime odt = OffsetDateTime.parse (string , f); 
     System.out.println ("GOOD - string: " + string + " parsed: " + odt); 
    } catch (DateTimeParseException e) { 
     System.out.println ("ERROR - Failed to parse string: " + string); 
    } 
} 
System.out.println ("Done with 'DateTimeFormatter.ofPattern'."); 
ERROR - Failed to parse string: 2017-01-09T21:49:26.7Z 
GOOD - string: 2017-01-09T21:49:26.70Z parsed: 2017-01-09T21:49:26.700Z 
GOOD - string: 2017-01-09T21:49:26.700Z parsed: 2017-01-09T21:49:26.700Z 
ERROR - Failed to parse string: 2017-01-09T21:49:26.7000Z 
ERROR - Failed to parse string: 2017-01-09T21:49:26.70000Z 

ISO 8601

FYI、例えば2017-01-09T21:49:26.70Zような文字列の形式はISO 8601規格で定義されています。 java.timeクラスは、日付時刻値を表す文字列を解析または生成するときに、デフォルトでこれらの標準ISO 8601形式を使用します。

この特定の形式では、Tを使用して、年月日部分と時分秒部分を区切ります。 ZZuluの略で、UTCを意味します。

さらに詳しい情報はsearching StackOverflowで確認できます。

+0

1.8.0.121に更新され、パターンを使用して" 2017-01-09T21:49:26.7Z " "yyyy-MM-dd'T'HH:mm:ss [.SSS] XXX" –

+1

@AdamBronfin @JsonFormatを完全に削除します。そうすれば、ジャクソンは 'InstantTime parse'が使用する' DateTimeFormatter.ISO_INSTANT'を使用します。これはバジルがここで示唆しているものです。 –

+0

@SotiriosDelimanolis私は実験としてのあなたの提案に同意します。しかし、私は彼の書式設定パターンが 'DateTimeFormatter.ISO_INSTANT'だけでなく動作するはずであることを示すコードを追加しました。 –

関連する問題