Skip to content

Commit

Permalink
[#19921] Add RFC 3339 compatible Jackson module for java.time types
Browse files Browse the repository at this point in the history
  • Loading branch information
beikov committed Oct 20, 2024
1 parent 266193f commit c0703e3
Show file tree
Hide file tree
Showing 172 changed files with 5,788 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,8 @@ public void processOpts() {
additionalProperties.remove(SERIALIZATION_LIBRARY_GSON);
additionalProperties.remove(SERIALIZATION_LIBRARY_JSONB);
supportingFiles.add(new SupportingFile("RFC3339DateFormat.mustache", invokerFolder, "RFC3339DateFormat.java"));
supportingFiles.add(new SupportingFile("RFC3339InstantDeserializer.mustache", invokerFolder, "RFC3339InstantDeserializer.java"));
supportingFiles.add(new SupportingFile("RFC3339JavaTimeModule.mustache", invokerFolder, "RFC3339JavaTimeModule.java"));
break;
case SERIALIZATION_LIBRARY_GSON:
additionalProperties.put(SERIALIZATION_LIBRARY_GSON, "true");
Expand Down
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(
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
Expand Up @@ -149,6 +149,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
{{#openApiNullable}}
objectMapper.registerModule(new JsonNullableModule());
{{/openApiNullable}}
objectMapper.registerModule(new RFC3339JavaTimeModule());
objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());

dateFormat = ApiClient.buildDefaultDateFormat();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ public class ApiClient {
{{/joda}}
objectMapper.registerModule(new JavaTimeModule());
{{#openApiNullable}}
objectMapper.registerModule(new RFC3339JavaTimeModule());
JsonNullableModule jnm = new JsonNullableModule();
objectMapper.registerModule(jnm);
{{/openApiNullable}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class JSON implements ContextResolver<ObjectMapper> {
{{#openApiNullable}}
.addModule(new JsonNullableModule())
{{/openApiNullable}}
.addModule(new RFC3339JavaTimeModule())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class JSON implements ContextResolver<ObjectMapper> {
{{#openApiNullable}}
.addModule(new JsonNullableModule())
{{/openApiNullable}}
.addModule(new RFC3339JavaTimeModule())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ public class ApiClient {
{{#openApiNullable}}
mapper.registerModule(new JsonNullableModule());
{{/openApiNullable}}
mapper.registerModule(new RFC3339JavaTimeModule());
return mapper;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ public void testSupportedSecuritySchemesJersey() {

List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();

assertThat(files).hasSize(32);
assertThat(files).hasSize(34);
validateJavaSourceFiles(files);
assertThat(output.resolve("src/main/java/xyz/abcdef/api/DefaultApi.java")).content().contains(
"public class DefaultApi",
Expand Down Expand Up @@ -586,7 +586,7 @@ public void testSupportedSecuritySchemesJersey() {

List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();

assertThat(files).hasSize(35);
assertThat(files).hasSize(37);

validateJavaSourceFiles(files);
assertThat(output.resolve("src/main/java/xyz/abcdef/api/PingApi.java")).content().contains(
Expand Down Expand Up @@ -1389,7 +1389,7 @@ public void testRestTemplateWithFreeFormInQueryParameters() {
List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();

validateJavaSourceFiles(files);
assertThat(files).hasSize(35);
assertThat(files).hasSize(37);
TestUtils.assertFileContains(output.resolve("src/main/java/xyz/abcdef/ApiClient.java"),
"public static String urlEncode(String s) { return URLEncoder.encode(s,"
+ " UTF_8).replaceAll(\"\\\\+\", \"%20\"); }"
Expand All @@ -1411,7 +1411,7 @@ public void testRestTemplateWithFreeFormInQueryParameters() {
List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();

validateJavaSourceFiles(files);
assertThat(files).hasSize(38);
assertThat(files).hasSize(40);
assertThat(output.resolve("src/main/java/xyz/abcdef/api/DefaultApi.java")).content()
.contains(
"localVarQueryParams.addAll(ApiClient.parameterToPairs(\"since\", queryObject.getSince()));",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void testApacheHttpClientExplodedQueryParamObject() throws IOException {
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();

Assert.assertEquals(files.size(), 42);
Assert.assertEquals(files.size(), 44);
validateJavaSourceFiles(files);

TestUtils.assertFileContains(Paths.get(output + "/src/main/java/xyz/abcdef/api/DefaultApi.java"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ src/main/java/org/openapitools/client/Configuration.java
src/main/java/org/openapitools/client/JavaTimeFormatter.java
src/main/java/org/openapitools/client/Pair.java
src/main/java/org/openapitools/client/RFC3339DateFormat.java
src/main/java/org/openapitools/client/RFC3339InstantDeserializer.java
src/main/java/org/openapitools/client/RFC3339JavaTimeModule.java
src/main/java/org/openapitools/client/ServerConfiguration.java
src/main/java/org/openapitools/client/ServerVariable.java
src/main/java/org/openapitools/client/StringUtil.java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public ApiClient(CloseableHttpClient httpClient) {
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
objectMapper.registerModule(new JavaTimeModule());
objectMapper.registerModule(new JsonNullableModule());
objectMapper.registerModule(new RFC3339JavaTimeModule());
objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());

dateFormat = ApiClient.buildDefaultDateFormat();
Expand Down
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);
}
}
2 changes: 2 additions & 0 deletions samples/client/echo_api/java/native/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ src/main/java/org/openapitools/client/Configuration.java
src/main/java/org/openapitools/client/JSON.java
src/main/java/org/openapitools/client/Pair.java
src/main/java/org/openapitools/client/RFC3339DateFormat.java
src/main/java/org/openapitools/client/RFC3339InstantDeserializer.java
src/main/java/org/openapitools/client/RFC3339JavaTimeModule.java
src/main/java/org/openapitools/client/ServerConfiguration.java
src/main/java/org/openapitools/client/ServerVariable.java
src/main/java/org/openapitools/client/api/AuthApi.java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ protected ObjectMapper createDefaultObjectMapper() {
mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
mapper.registerModule(new JavaTimeModule());
mapper.registerModule(new JsonNullableModule());
mapper.registerModule(new RFC3339JavaTimeModule());
return mapper;
}

Expand Down
Loading

0 comments on commit c0703e3

Please sign in to comment.