Skip to content

Commit dfc381c

Browse files
authored
[Java] Add a new additional property to configure Jackson's failOnUnknownProperties (#19271)
* [Java] Add a new additional property to configure Jackson's `failOnUnknownProperties` * Move `FAIL_ON_UNKNOWN_PROPERTIES` property to JavaClientCodegen * Template `FAIL_ON_UNKNOWN_PROPERTIES` for other libraries beside retrofit2 * Default `failOnUnknownProperties` to false for all Java Client libraries * Fix integration tests Add the `failOnUnknownProperties: true` additional properties to generate the expected mapper
1 parent 082382c commit dfc381c

File tree

30 files changed

+59
-21
lines changed

30 files changed

+59
-21
lines changed

bin/configs/java-jersey2-8.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ additionalProperties:
1111
useOneOfDiscriminatorLookup: true
1212
disallowAdditionalPropertiesIfNotPresent: false
1313
gradleProperties: "\n# JVM arguments\norg.gradle.jvmargs=-Xmx2024m -XX:MaxPermSize=512m\n# set timeout\norg.gradle.daemon.idletimeout=3600000\n# show all warnings\norg.gradle.warning.mode=all"
14+
failOnUnknownProperties: true

bin/configs/java-jersey3.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ additionalProperties:
1212
useOneOfDiscriminatorLookup: true
1313
disallowAdditionalPropertiesIfNotPresent: false
1414
gradleProperties: "\n# JVM arguments\norg.gradle.jvmargs=-Xmx2024m -XX:MaxPermSize=512m\n# set timeout\norg.gradle.daemon.idletimeout=3600000\n# show all warnings\norg.gradle.warning.mode=all"
15+
failOnUnknownProperties: true

docs/generators/java-microprofile.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
4949
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
5050
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
5151
|errorObjectType|Error Object type. (This option is for okhttp-gson only)| |null|
52+
|failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false|
5253
|generateBuilders|Whether to generate builders for models| |false|
5354
|generateClientAsBean|For resttemplate, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false|
5455
|generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false|

docs/generators/java.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
4949
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
5050
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
5151
|errorObjectType|Error Object type. (This option is for okhttp-gson only)| |null|
52+
|failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false|
5253
|generateBuilders|Whether to generate builders for models| |false|
5354
|generateClientAsBean|For resttemplate, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false|
5455
|generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
100100
public static final String MICROPROFILE_KUMULUZEE = "kumuluzee";
101101
public static final String WEBCLIENT_BLOCKING_OPERATIONS = "webclientBlockingOperations";
102102
public static final String USE_ENUM_CASE_INSENSITIVE = "useEnumCaseInsensitive";
103+
public static final String FAIL_ON_UNKNOWN_PROPERTIES = "failOnUnknownProperties";
103104

104105
public static final String SERIALIZATION_LIBRARY_GSON = "gson";
105106
public static final String SERIALIZATION_LIBRARY_JACKSON = "jackson";
@@ -134,6 +135,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
134135
@Setter protected boolean withAWSV4Signature = false;
135136
@Setter protected String gradleProperties;
136137
@Setter protected String errorObjectType;
138+
@Getter @Setter protected boolean failOnUnknownProperties = false;
137139
protected String authFolder;
138140
/**
139141
* Serialization library.
@@ -240,6 +242,7 @@ public JavaClientCodegen() {
240242
cliOptions.add(CliOption.newBoolean(GENERATE_CLIENT_AS_BEAN, "For resttemplate, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).", this.generateClientAsBean));
241243
cliOptions.add(CliOption.newBoolean(SUPPORT_URL_QUERY, "Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries."));
242244
cliOptions.add(CliOption.newBoolean(USE_ENUM_CASE_INSENSITIVE, "Use `equalsIgnoreCase` when String for enum comparison", useEnumCaseInsensitive));
245+
cliOptions.add(CliOption.newBoolean(FAIL_ON_UNKNOWN_PROPERTIES, "Fail Jackson de-serialization on unknown properties", this.failOnUnknownProperties));
243246

244247
supportedLibraries.put(JERSEY2, "HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.17.1");
245248
supportedLibraries.put(JERSEY3, "HTTP client: Jersey client 3.1.1. JSON processing: Jackson 2.17.1");
@@ -390,6 +393,7 @@ public void processOpts() {
390393
convertPropertyToStringAndWriteBack(GRADLE_PROPERTIES, this::setGradleProperties);
391394
convertPropertyToStringAndWriteBack(ERROR_OBJECT_TYPE, this::setErrorObjectType);
392395
convertPropertyToBooleanAndWriteBack(WEBCLIENT_BLOCKING_OPERATIONS, op -> webclientBlockingOperations=op);
396+
convertPropertyToBooleanAndWriteBack(FAIL_ON_UNKNOWN_PROPERTIES, this::setFailOnUnknownProperties);
393397

394398
// add URL query deepObject support to native, apache-httpclient by default
395399
if (!additionalProperties.containsKey(SUPPORT_URL_QUERY)) {

modules/openapi-generator/src/main/resources/Java/libraries/apache-httpclient/ApiClient.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
137137
public ApiClient(CloseableHttpClient httpClient) {
138138
objectMapper = new ObjectMapper();
139139
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
140-
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
140+
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, {{failOnUnknownProperties}});
141141
objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
142142
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
143143
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);

modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiClient.mustache

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,12 @@ public class ApiClient {
173173
ObjectMapper objectMapper = new ObjectMapper();
174174
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
175175
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
176+
{{#failOnUnknownProperties}}
177+
objectMapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
178+
{{/failOnUnknownProperties}}
179+
{{^failOnUnknownProperties}}
176180
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
181+
{{/failOnUnknownProperties}}
177182
objectMapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
178183
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
179184
objectMapper.setDateFormat(new RFC3339DateFormat());

modules/openapi-generator/src/main/resources/Java/libraries/google-api-client/ApiClient.mustache

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ public class ApiClient {
3434
// A reasonable default object mapper. Client can pass in a chosen ObjectMapper anyway, this is just for reasonable defaults.
3535
private static ObjectMapper createDefaultObjectMapper() {
3636
ObjectMapper objectMapper = new ObjectMapper()
37+
{{#failOnUnknownProperties}}
38+
.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
39+
{{/failOnUnknownProperties}}
40+
{{^failOnUnknownProperties}}
3741
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
42+
{{/failOnUnknownProperties}}
3843
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
3944
.setDateFormat(new RFC3339DateFormat());
4045
{{#joda}}

modules/openapi-generator/src/main/resources/Java/libraries/jersey2/JSON.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class JSON implements ContextResolver<ObjectMapper> {
3232
mapper = JsonMapper.builder()
3333
.serializationInclusion(JsonInclude.Include.NON_NULL)
3434
.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false)
35-
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
35+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, {{failOnUnknownProperties}})
3636
.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true)
3737
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
3838
.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)

modules/openapi-generator/src/main/resources/Java/libraries/jersey3/JSON.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class JSON implements ContextResolver<ObjectMapper> {
3232
mapper = JsonMapper.builder()
3333
.serializationInclusion(JsonInclude.Include.NON_NULL)
3434
.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false)
35-
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
35+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, {{failOnUnknownProperties}})
3636
.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true)
3737
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
3838
.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)

0 commit comments

Comments
 (0)