2017-12-21 8 views
0

SpringブートでJSONペイロードを返すRESTサービスを作成すると、Java 8のLocalDateTimeがシリアル化されます。 (おそらく)ジャクソンがオブジェクトを文字列にマーシャリングするときに適用されるフォーマット文字列(つまりパターン)はどこにありますか?また、そのフォーマットを適用する(つまりフォーマッタを設定する)Spring Bootのデフォルト設定をどこで見つけることができますか?Spring BootはどこでデフォルトのJSON日付(つまりLocalDateTime)形式を定義していますか?

(NB:私はペイロードに、フォーマットされた日付ではなく、タイムスタンプを参照することができる。)

+2

LocalDateTimeはタイムスタンプではないため、タイムスタンプは表示されません。つまり、ドキュメントはあなたの質問に答えます:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-customize-the-jackson-objectmapper –

+0

ドキュメントは私に['Jackson2ObjectMapperBuilder '](http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-web/4.1.1.RELEASE/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java#460 )、これは['JSR310Module']を指します(http://grepcode.com/file/repo1.maven.org/maven2/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.4.4/com /fasterxml/jackson/datatype/jsr310/JSR310Module.java#129)、via – Christian

+0

... ['LocalDateTimeSerializer'](http://grepcode.com/file/repo1.maven.org/maven2/com。最終的に['LocalDateTime :: toString'](http:// grepcode)に変更してください。 .com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b 25/java/time/LocalDateTime.java#1965)。私の 'LocalDateTime'は' 1776-07-04T12:29Z'に設定されていますが、 '1776-07-04T12:29:00Z'になります。 Docsは "使用されるフォーマットは、省略された部分がゼロであることが暗示されている最短になります"と言っています: "uuuu-MM-dd'T'HH:mm'。なぜ私は ':00'を返すのですか? – Christian

答えて

0

Jackson2ObjectMapperBuilder行う複数のモジュールを登録するregisterWellKnownModulesIfAvailable方法ではかなり難しいロジック。 Javaの8時間のために特に:アプリケーションがjackson-datatype-jsr310モジュールスプリングに依存している場合

// Java 8 java.time package present? 
if (ClassUtils.isPresent("java.time.LocalDate", this.moduleClassLoader)) { 
    try { 
     Class<? extends Module> javaTimeModule = (Class<? extends Module>) 
       ClassUtils.forName("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", this.moduleClassLoader); 
     objectMapper.registerModule(BeanUtils.instantiateClass(javaTimeModule)); 
    } 
    catch (ClassNotFoundException ex) { 
     // jackson-datatype-jsr310 not available 
    } 
} 

だから黙ってそれを登録します。結果として、このモジュールからjava時間型用の専用のシリアライザ/デシリアライザが用意されます。あなたは LocalDateTimeSerializerで興味深いです。あなたが見ることができるように、シリアル化ロジックは useTimestampに依存しています。あなたのケースではfalseを返すので、 elseブランチに移動します。デフォルトで _formatterはヌルで、 _defaultFormatter()が使用されます。これは DateTimeFormatter.ISO_LOCAL_DATE_TIMEです。日付を文字列としてシリアル化する場合、または ifブランチのシリアル化ロジックを使用して、メソッドからメソッドを返す場合は、カスタムフォーマッタを使用してこの動作を簡単に更新できます。

@Override 
public void serialize(LocalDateTime value, JsonGenerator g, SerializerProvider provider) 
    throws IOException 
{ 
    if (useTimestamp(provider)) { 
     g.writeStartArray(); 
     g.writeNumber(value.getYear()); 
     g.writeNumber(value.getMonthValue()); 
     g.writeNumber(value.getDayOfMonth()); 
     g.writeNumber(value.getHour()); 
     g.writeNumber(value.getMinute()); 
     if (value.getSecond() > 0 || value.getNano() > 0) { 
      g.writeNumber(value.getSecond()); 
      if(value.getNano() > 0) { 
       if (provider.isEnabled(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)) 
        g.writeNumber(value.getNano()); 
       else 
        g.writeNumber(value.get(ChronoField.MILLI_OF_SECOND)); 
      } 
     } 
     g.writeEndArray(); 
    } else { 
     DateTimeFormatter dtf = _formatter; 
     if (dtf == null) { 
      dtf = _defaultFormatter(); 
     } 
     g.writeString(value.format(dtf)); 
    } 
} 

// since 2.7: TODO in 2.8; change to use per-type defaulting 
protected DateTimeFormatter _defaultFormatter() { 
    return DateTimeFormatter.ISO_LOCAL_DATE_TIME; 
} 

protected boolean useTimestamp(SerializerProvider provider) { 
    if (_useTimestamp != null) { 
     return _useTimestamp.booleanValue(); 
    } 
    // assume that explicit formatter definition implies use of textual format 
    if (_formatter != null) { 
     return false; 
    } 
    return provider.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 
} 
関連する問題