-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[#19921] Add RFC 3339 compatible Jackson module for java.time types #19925
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
{{>licenseInfo}} | ||
package {{invokerPackage}}; | ||
|
||
import java.io.IOException; | ||
import java.time.Instant; | ||
import java.time.OffsetDateTime; | ||
import java.time.ZoneId; | ||
import java.time.ZonedDateTime; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.temporal.Temporal; | ||
import java.time.temporal.TemporalAccessor; | ||
import java.util.function.BiFunction; | ||
import java.util.function.Function; | ||
|
||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.databind.DeserializationContext; | ||
import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer; | ||
|
||
{{>generatedAnnotation}} | ||
public class RFC3339InstantDeserializer<T extends Temporal> extends InstantDeserializer<T> { | ||
|
||
public static final RFC3339InstantDeserializer<Instant> INSTANT = new RFC3339InstantDeserializer<>( | ||
Instant.class, DateTimeFormatter.ISO_INSTANT, | ||
Instant::from, | ||
a -> Instant.ofEpochMilli( a.value ), | ||
a -> Instant.ofEpochSecond( a.integer, a.fraction ), | ||
null, | ||
true // yes, replace zero offset with Z | ||
); | ||
|
||
public static final RFC3339InstantDeserializer<OffsetDateTime> OFFSET_DATE_TIME = new RFC3339InstantDeserializer<>( | ||
OffsetDateTime.class, DateTimeFormatter.ISO_OFFSET_DATE_TIME, | ||
OffsetDateTime::from, | ||
a -> OffsetDateTime.ofInstant( Instant.ofEpochMilli( a.value ), a.zoneId ), | ||
a -> OffsetDateTime.ofInstant( Instant.ofEpochSecond( a.integer, a.fraction ), a.zoneId ), | ||
(d, z) -> ( d.isEqual( OffsetDateTime.MIN ) || d.isEqual( OffsetDateTime.MAX ) ? | ||
d : | ||
d.withOffsetSameInstant( z.getRules().getOffset( d.toLocalDateTime() ) ) ), | ||
true // yes, replace zero offset with Z | ||
); | ||
|
||
public static final RFC3339InstantDeserializer<ZonedDateTime> ZONED_DATE_TIME = new RFC3339InstantDeserializer<>( | ||
ZonedDateTime.class, DateTimeFormatter.ISO_ZONED_DATE_TIME, | ||
ZonedDateTime::from, | ||
a -> ZonedDateTime.ofInstant( Instant.ofEpochMilli( a.value ), a.zoneId ), | ||
a -> ZonedDateTime.ofInstant( Instant.ofEpochSecond( a.integer, a.fraction ), a.zoneId ), | ||
ZonedDateTime::withZoneSameInstant, | ||
false // keep zero offset and Z separate since zones explicitly supported | ||
); | ||
|
||
protected RFC3339InstantDeserializer( | ||
Class<T> supportedType, | ||
DateTimeFormatter formatter, | ||
Function<TemporalAccessor, T> parsedToValue, | ||
Function<FromIntegerArguments, T> fromMilliseconds, | ||
Function<FromDecimalArguments, T> fromNanoseconds, | ||
BiFunction<T, ZoneId, T> adjust, | ||
boolean replaceZeroOffsetAsZ) { | ||
super( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This super constructor is deprecated (see here). Could you please switch to a different one? I guess you could simply use the one recommended in the above link. And for the additional parameters required there, you could use the default values. (DEFAULT_NORMALIZE_ZONE_ID=true, DEFAULT_ALWAYS_ALLOW_STRINGIFIED_DATE_TIMESTAMPS=false) |
||
supportedType, | ||
formatter, | ||
parsedToValue, | ||
fromMilliseconds, | ||
fromNanoseconds, | ||
adjust, | ||
replaceZeroOffsetAsZ | ||
); | ||
} | ||
|
||
@Override | ||
protected T _fromString(JsonParser p, DeserializationContext ctxt, String string0) throws IOException { | ||
return super._fromString(p, ctxt, string0.replace( ' ', 'T' )); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{{>licenseInfo}} | ||
package {{invokerPackage}}; | ||
|
||
import java.time.Instant; | ||
import java.time.OffsetDateTime; | ||
import java.time.ZonedDateTime; | ||
|
||
import com.fasterxml.jackson.databind.module.SimpleModule; | ||
|
||
{{>generatedAnnotation}} | ||
public class RFC3339JavaTimeModule extends SimpleModule { | ||
|
||
public RFC3339JavaTimeModule() { | ||
super("RFC3339JavaTimeModule"); | ||
|
||
addDeserializer(Instant.class, RFC3339InstantDeserializer.INSTANT); | ||
addDeserializer(OffsetDateTime.class, RFC3339InstantDeserializer.OFFSET_DATE_TIME); | ||
addDeserializer(ZonedDateTime.class, RFC3339InstantDeserializer.ZONED_DATE_TIME); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -187,6 +187,7 @@ public class ApiClient { | |
{{/joda}} | ||
objectMapper.registerModule(new JavaTimeModule()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The JavaTimeModule can already deserialize RFC3339 datetimes |
||
{{#openApiNullable}} | ||
objectMapper.registerModule(new RFC3339JavaTimeModule()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this new line shouldn't be inside the |
||
JsonNullableModule jnm = new JsonNullableModule(); | ||
objectMapper.registerModule(jnm); | ||
{{/openApiNullable}} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* Echo Server API | ||
* Echo Server API | ||
* | ||
* The version of the OpenAPI document: 0.1.0 | ||
* Contact: [email protected] | ||
* | ||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). | ||
* https://openapi-generator.tech | ||
* Do not edit the class manually. | ||
*/ | ||
|
||
package org.openapitools.client; | ||
|
||
import java.io.IOException; | ||
import java.time.Instant; | ||
import java.time.OffsetDateTime; | ||
import java.time.ZoneId; | ||
import java.time.ZonedDateTime; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.temporal.Temporal; | ||
import java.time.temporal.TemporalAccessor; | ||
import java.util.function.BiFunction; | ||
import java.util.function.Function; | ||
|
||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.databind.DeserializationContext; | ||
import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer; | ||
|
||
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.10.0-SNAPSHOT") | ||
public class RFC3339InstantDeserializer<T extends Temporal> extends InstantDeserializer<T> { | ||
|
||
public static final RFC3339InstantDeserializer<Instant> INSTANT = new RFC3339InstantDeserializer<>( | ||
Instant.class, DateTimeFormatter.ISO_INSTANT, | ||
Instant::from, | ||
a -> Instant.ofEpochMilli( a.value ), | ||
a -> Instant.ofEpochSecond( a.integer, a.fraction ), | ||
null, | ||
true // yes, replace zero offset with Z | ||
); | ||
|
||
public static final RFC3339InstantDeserializer<OffsetDateTime> OFFSET_DATE_TIME = new RFC3339InstantDeserializer<>( | ||
OffsetDateTime.class, DateTimeFormatter.ISO_OFFSET_DATE_TIME, | ||
OffsetDateTime::from, | ||
a -> OffsetDateTime.ofInstant( Instant.ofEpochMilli( a.value ), a.zoneId ), | ||
a -> OffsetDateTime.ofInstant( Instant.ofEpochSecond( a.integer, a.fraction ), a.zoneId ), | ||
(d, z) -> ( d.isEqual( OffsetDateTime.MIN ) || d.isEqual( OffsetDateTime.MAX ) ? | ||
d : | ||
d.withOffsetSameInstant( z.getRules().getOffset( d.toLocalDateTime() ) ) ), | ||
true // yes, replace zero offset with Z | ||
); | ||
|
||
public static final RFC3339InstantDeserializer<ZonedDateTime> ZONED_DATE_TIME = new RFC3339InstantDeserializer<>( | ||
ZonedDateTime.class, DateTimeFormatter.ISO_ZONED_DATE_TIME, | ||
ZonedDateTime::from, | ||
a -> ZonedDateTime.ofInstant( Instant.ofEpochMilli( a.value ), a.zoneId ), | ||
a -> ZonedDateTime.ofInstant( Instant.ofEpochSecond( a.integer, a.fraction ), a.zoneId ), | ||
ZonedDateTime::withZoneSameInstant, | ||
false // keep zero offset and Z separate since zones explicitly supported | ||
); | ||
|
||
protected RFC3339InstantDeserializer( | ||
Class<T> supportedType, | ||
DateTimeFormatter formatter, | ||
Function<TemporalAccessor, T> parsedToValue, | ||
Function<FromIntegerArguments, T> fromMilliseconds, | ||
Function<FromDecimalArguments, T> fromNanoseconds, | ||
BiFunction<T, ZoneId, T> adjust, | ||
boolean replaceZeroOffsetAsZ) { | ||
super( | ||
supportedType, | ||
formatter, | ||
parsedToValue, | ||
fromMilliseconds, | ||
fromNanoseconds, | ||
adjust, | ||
replaceZeroOffsetAsZ | ||
); | ||
} | ||
|
||
@Override | ||
protected T _fromString(JsonParser p, DeserializationContext ctxt, String string0) throws IOException { | ||
return super._fromString(p, ctxt, string0.replace( ' ', 'T' )); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Echo Server API | ||
* Echo Server API | ||
* | ||
* The version of the OpenAPI document: 0.1.0 | ||
* Contact: [email protected] | ||
* | ||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). | ||
* https://openapi-generator.tech | ||
* Do not edit the class manually. | ||
*/ | ||
|
||
package org.openapitools.client; | ||
|
||
import java.time.Instant; | ||
import java.time.OffsetDateTime; | ||
import java.time.ZonedDateTime; | ||
|
||
import com.fasterxml.jackson.databind.module.SimpleModule; | ||
|
||
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.10.0-SNAPSHOT") | ||
public class RFC3339JavaTimeModule extends SimpleModule { | ||
|
||
public RFC3339JavaTimeModule() { | ||
super("RFC3339JavaTimeModule"); | ||
|
||
addDeserializer(Instant.class, RFC3339InstantDeserializer.INSTANT); | ||
addDeserializer(OffsetDateTime.class, RFC3339InstantDeserializer.OFFSET_DATE_TIME); | ||
addDeserializer(ZonedDateTime.class, RFC3339InstantDeserializer.ZONED_DATE_TIME); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional, not required for PR approval imo: Currently these supporting files are added even if the chosen library doesn't use them at all. You could introduce an additional
if
here to only add the files where they are actually supported.