Skip to content

Commit 3c693a2

Browse files
committed
[BUG][JAVA][okhttp-gson] Skip validateJsonElement for ref'd enum properties
A property that is both isModel and isEnum (a $ref to a top-level enum schema) was emitting MyEnum.validateJsonElement(...) inside the parent class's validateJsonElement, which doesn't exist on enum classes and breaks compilation. This is the same surface as #18547 narrowed to the enum case. Add an {{^isEnum}} guard inside the {{#isModel}} block so the call is only emitted for non-enum models; the dedicated {{#isEnum}} branch already below handles enum validation correctly. Test: NullableFieldsMapResponse (anyOf wrapper of a success/error pair with nullable required fields) added to the okhttp-gson fake petstore; two JSONTest cases verify deserialization round-trips when nullable required fields are null. Refs #18547
1 parent 2917ce8 commit 3c693a2

21 files changed

Lines changed: 1734 additions & 0 deletions

modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pojo.mustache

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
434434
}
435435
{{/isString}}
436436
{{#isModel}}
437+
{{^isEnum}}
437438
{{#required}}
438439
{{#isNullable}}
439440
if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
@@ -450,6 +451,7 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
450451
{{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
451452
}
452453
{{/required}}
454+
{{/isEnum}}
453455
{{/isModel}}
454456
{{#isEnum}}
455457
{{#required}}

modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,20 @@ paths:
961961
- type: array
962962
items:
963963
type: integer
964+
/fake/nullable-required-fields-anyof:
965+
get:
966+
tags:
967+
- fake
968+
summary: test anyOf with map of objects containing nullable required fields
969+
description: 'Tests that anyOf deserialization works when object values contain required fields that are nullable (e.g. Record<string, { before: string | null, after: string | null }>)'
970+
operationId: testNullableRequiredFieldsAnyOf
971+
responses:
972+
'200':
973+
description: successful operation
974+
content:
975+
application/json:
976+
schema:
977+
$ref: '#/components/schemas/NullableFieldsMapResponse'
964978
/fake/anyOfWIthSameErasure:
965979
get:
966980
description: Test route, this shouldn't cause a compiler error
@@ -2866,3 +2880,46 @@ components:
28662880
allOf:
28672881
- $ref: '#/components/schemas/Height'
28682882
default: 32.1
2883+
NullableFieldsValue:
2884+
description: "Object with required but nullable string fields"
2885+
type: object
2886+
properties:
2887+
before:
2888+
type: string
2889+
nullable: true
2890+
after:
2891+
type: string
2892+
nullable: true
2893+
required:
2894+
- before
2895+
- after
2896+
NullableFieldsMapSuccess:
2897+
description: "Success response containing a map of objects with nullable fields"
2898+
type: object
2899+
additionalProperties: false
2900+
properties:
2901+
status:
2902+
type: string
2903+
positions:
2904+
type: object
2905+
additionalProperties:
2906+
$ref: '#/components/schemas/NullableFieldsValue'
2907+
required:
2908+
- status
2909+
- positions
2910+
NullableFieldsMapError:
2911+
description: "Error response"
2912+
type: object
2913+
additionalProperties: false
2914+
properties:
2915+
status:
2916+
type: string
2917+
reason:
2918+
type: string
2919+
required:
2920+
- status
2921+
- reason
2922+
NullableFieldsMapResponse:
2923+
anyOf:
2924+
- $ref: '#/components/schemas/NullableFieldsMapSuccess'
2925+
- $ref: '#/components/schemas/NullableFieldsMapError'

samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ docs/NewPetCategoryInlineAllof.md
8080
docs/NewPetCategoryInlineAllofAllOfCategoryTag.md
8181
docs/NullableClass.md
8282
docs/NullableEnum.md
83+
docs/NullableFieldsMapError.md
84+
docs/NullableFieldsMapResponse.md
85+
docs/NullableFieldsMapSuccess.md
86+
docs/NullableFieldsValue.md
8387
docs/NullableShape.md
8488
docs/NumberOnly.md
8589
docs/ObjectWithDeprecatedFields.md
@@ -231,6 +235,10 @@ src/main/java/org/openapitools/client/model/NewPetCategoryInlineAllof.java
231235
src/main/java/org/openapitools/client/model/NewPetCategoryInlineAllofAllOfCategoryTag.java
232236
src/main/java/org/openapitools/client/model/NullableClass.java
233237
src/main/java/org/openapitools/client/model/NullableEnum.java
238+
src/main/java/org/openapitools/client/model/NullableFieldsMapError.java
239+
src/main/java/org/openapitools/client/model/NullableFieldsMapResponse.java
240+
src/main/java/org/openapitools/client/model/NullableFieldsMapSuccess.java
241+
src/main/java/org/openapitools/client/model/NullableFieldsValue.java
234242
src/main/java/org/openapitools/client/model/NullableShape.java
235243
src/main/java/org/openapitools/client/model/NumberOnly.java
236244
src/main/java/org/openapitools/client/model/ObjectWithDeprecatedFields.java
@@ -269,3 +277,7 @@ src/main/java/org/openapitools/client/model/Value.java
269277
src/main/java/org/openapitools/client/model/Variable.java
270278
src/main/java/org/openapitools/client/model/Whale.java
271279
src/main/java/org/openapitools/client/model/Zebra.java
280+
src/test/java/org/openapitools/client/model/NullableFieldsMapErrorTest.java
281+
src/test/java/org/openapitools/client/model/NullableFieldsMapResponseTest.java
282+
src/test/java/org/openapitools/client/model/NullableFieldsMapSuccessTest.java
283+
src/test/java/org/openapitools/client/model/NullableFieldsValueTest.java

samples/client/petstore/java/okhttp-gson/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ Class | Method | HTTP request | Description
142142
*FakeApi* | [**testInlineAdditionalProperties**](docs/FakeApi.md#testInlineAdditionalProperties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties
143143
*FakeApi* | [**testInlineFreeformAdditionalProperties**](docs/FakeApi.md#testInlineFreeformAdditionalProperties) | **POST** /fake/inline-freeform-additionalProperties | test inline free-form additionalProperties
144144
*FakeApi* | [**testJsonFormData**](docs/FakeApi.md#testJsonFormData) | **GET** /fake/jsonFormData | test json serialization of form data
145+
*FakeApi* | [**testNullableRequiredFieldsAnyOf**](docs/FakeApi.md#testNullableRequiredFieldsAnyOf) | **GET** /fake/nullable-required-fields-anyof | test anyOf with map of objects containing nullable required fields
145146
*FakeApi* | [**testQueryParameterCollectionFormat**](docs/FakeApi.md#testQueryParameterCollectionFormat) | **PUT** /fake/test-query-parameters |
146147
*FakeApi* | [**testStringMapReference**](docs/FakeApi.md#testStringMapReference) | **POST** /fake/stringMap-reference | test referenced string map
147148
*FakeClassnameTags123Api* | [**testClassname**](docs/FakeClassnameTags123Api.md#testClassname) | **PATCH** /fake_classname_test | To test class name in snake case
@@ -242,6 +243,10 @@ Class | Method | HTTP request | Description
242243
- [NewPetCategoryInlineAllofAllOfCategoryTag](docs/NewPetCategoryInlineAllofAllOfCategoryTag.md)
243244
- [NullableClass](docs/NullableClass.md)
244245
- [NullableEnum](docs/NullableEnum.md)
246+
- [NullableFieldsMapError](docs/NullableFieldsMapError.md)
247+
- [NullableFieldsMapResponse](docs/NullableFieldsMapResponse.md)
248+
- [NullableFieldsMapSuccess](docs/NullableFieldsMapSuccess.md)
249+
- [NullableFieldsValue](docs/NullableFieldsValue.md)
245250
- [NullableShape](docs/NullableShape.md)
246251
- [NumberOnly](docs/NumberOnly.md)
247252
- [ObjectWithDeprecatedFields](docs/ObjectWithDeprecatedFields.md)

samples/client/petstore/java/okhttp-gson/api/openapi.yaml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,24 @@ paths:
10211021
description: successful response
10221022
x-accepts:
10231023
- application/json
1024+
/fake/nullable-required-fields-anyof:
1025+
get:
1026+
description: "Tests that anyOf deserialization works when object values contain\
1027+
\ required fields that are nullable (e.g. Record<string, { before: string\
1028+
\ | null, after: string | null }>)"
1029+
operationId: testNullableRequiredFieldsAnyOf
1030+
responses:
1031+
"200":
1032+
content:
1033+
application/json:
1034+
schema:
1035+
$ref: "#/components/schemas/NullableFieldsMapResponse"
1036+
description: successful operation
1037+
summary: test anyOf with map of objects containing nullable required fields
1038+
tags:
1039+
- fake
1040+
x-accepts:
1041+
- application/json
10241042
/fake/anyOfWIthSameErasure:
10251043
get:
10261044
description: "Test route, this shouldn't cause a compiler error"
@@ -2998,6 +3016,58 @@ components:
29983016
- $ref: "#/components/schemas/Height"
29993017
default: 32.1
30003018
type: object
3019+
NullableFieldsValue:
3020+
description: Object with required but nullable string fields
3021+
example:
3022+
before: before
3023+
after: after
3024+
properties:
3025+
before:
3026+
nullable: true
3027+
type: string
3028+
after:
3029+
nullable: true
3030+
type: string
3031+
required:
3032+
- after
3033+
- before
3034+
type: object
3035+
NullableFieldsMapSuccess:
3036+
additionalProperties: false
3037+
description: Success response containing a map of objects with nullable fields
3038+
example:
3039+
positions:
3040+
key:
3041+
before: before
3042+
after: after
3043+
status: status
3044+
properties:
3045+
status:
3046+
type: string
3047+
positions:
3048+
additionalProperties:
3049+
$ref: "#/components/schemas/NullableFieldsValue"
3050+
type: object
3051+
required:
3052+
- positions
3053+
- status
3054+
type: object
3055+
NullableFieldsMapError:
3056+
additionalProperties: false
3057+
description: Error response
3058+
properties:
3059+
status:
3060+
type: string
3061+
reason:
3062+
type: string
3063+
required:
3064+
- reason
3065+
- status
3066+
type: object
3067+
NullableFieldsMapResponse:
3068+
anyOf:
3069+
- $ref: "#/components/schemas/NullableFieldsMapSuccess"
3070+
- $ref: "#/components/schemas/NullableFieldsMapError"
30013071
_foo_get_default_response:
30023072
example:
30033073
string:

samples/client/petstore/java/okhttp-gson/docs/FakeApi.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ All URIs are relative to *http://petstore.swagger.io:80/v2*
2525
| [**testInlineAdditionalProperties**](FakeApi.md#testInlineAdditionalProperties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties |
2626
| [**testInlineFreeformAdditionalProperties**](FakeApi.md#testInlineFreeformAdditionalProperties) | **POST** /fake/inline-freeform-additionalProperties | test inline free-form additionalProperties |
2727
| [**testJsonFormData**](FakeApi.md#testJsonFormData) | **GET** /fake/jsonFormData | test json serialization of form data |
28+
| [**testNullableRequiredFieldsAnyOf**](FakeApi.md#testNullableRequiredFieldsAnyOf) | **GET** /fake/nullable-required-fields-anyof | test anyOf with map of objects containing nullable required fields |
2829
| [**testQueryParameterCollectionFormat**](FakeApi.md#testQueryParameterCollectionFormat) | **PUT** /fake/test-query-parameters | |
2930
| [**testStringMapReference**](FakeApi.md#testStringMapReference) | **POST** /fake/stringMap-reference | test referenced string map |
3031

@@ -1380,6 +1381,64 @@ No authorization required
13801381
|-------------|-------------|------------------|
13811382
| **200** | successful operation | - |
13821383

1384+
<a id="testNullableRequiredFieldsAnyOf"></a>
1385+
# **testNullableRequiredFieldsAnyOf**
1386+
> NullableFieldsMapResponse testNullableRequiredFieldsAnyOf()
1387+
1388+
test anyOf with map of objects containing nullable required fields
1389+
1390+
Tests that anyOf deserialization works when object values contain required fields that are nullable (e.g. Record&lt;string, { before: string | null, after: string | null }&gt;)
1391+
1392+
### Example
1393+
```java
1394+
// Import classes:
1395+
import org.openapitools.client.ApiClient;
1396+
import org.openapitools.client.ApiException;
1397+
import org.openapitools.client.Configuration;
1398+
import org.openapitools.client.models.*;
1399+
import org.openapitools.client.api.FakeApi;
1400+
1401+
public class Example {
1402+
public static void main(String[] args) {
1403+
ApiClient defaultClient = Configuration.getDefaultApiClient();
1404+
defaultClient.setBasePath("http://petstore.swagger.io:80/v2");
1405+
1406+
FakeApi apiInstance = new FakeApi(defaultClient);
1407+
try {
1408+
NullableFieldsMapResponse result = apiInstance.testNullableRequiredFieldsAnyOf();
1409+
System.out.println(result);
1410+
} catch (ApiException e) {
1411+
System.err.println("Exception when calling FakeApi#testNullableRequiredFieldsAnyOf");
1412+
System.err.println("Status code: " + e.getCode());
1413+
System.err.println("Reason: " + e.getResponseBody());
1414+
System.err.println("Response headers: " + e.getResponseHeaders());
1415+
e.printStackTrace();
1416+
}
1417+
}
1418+
}
1419+
```
1420+
1421+
### Parameters
1422+
This endpoint does not need any parameter.
1423+
1424+
### Return type
1425+
1426+
[**NullableFieldsMapResponse**](NullableFieldsMapResponse.md)
1427+
1428+
### Authorization
1429+
1430+
No authorization required
1431+
1432+
### HTTP request headers
1433+
1434+
- **Content-Type**: Not defined
1435+
- **Accept**: application/json
1436+
1437+
### HTTP response details
1438+
| Status code | Description | Response headers |
1439+
|-------------|-------------|------------------|
1440+
| **200** | successful operation | - |
1441+
13831442
<a id="testQueryParameterCollectionFormat"></a>
13841443
# **testQueryParameterCollectionFormat**
13851444
> testQueryParameterCollectionFormat(pipe, ioutil, http, url, context)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
3+
# NullableFieldsMapError
4+
5+
Error response
6+
7+
## Properties
8+
9+
| Name | Type | Description | Notes |
10+
|------------ | ------------- | ------------- | -------------|
11+
|**status** | **String** | | |
12+
|**reason** | **String** | | |
13+
14+
15+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
3+
# NullableFieldsMapResponse
4+
5+
6+
## Properties
7+
8+
| Name | Type | Description | Notes |
9+
|------------ | ------------- | ------------- | -------------|
10+
|**status** | **String** | | |
11+
|**positions** | [**Map&lt;String, NullableFieldsValue&gt;**](NullableFieldsValue.md) | | |
12+
|**reason** | **String** | | |
13+
14+
15+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
3+
# NullableFieldsMapSuccess
4+
5+
Success response containing a map of objects with nullable fields
6+
7+
## Properties
8+
9+
| Name | Type | Description | Notes |
10+
|------------ | ------------- | ------------- | -------------|
11+
|**status** | **String** | | |
12+
|**positions** | [**Map&lt;String, NullableFieldsValue&gt;**](NullableFieldsValue.md) | | |
13+
14+
15+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
3+
# NullableFieldsValue
4+
5+
Object with required but nullable string fields
6+
7+
## Properties
8+
9+
| Name | Type | Description | Notes |
10+
|------------ | ------------- | ------------- | -------------|
11+
|**before** | **String** | | |
12+
|**after** | **String** | | |
13+
14+
15+

0 commit comments

Comments
 (0)