-
Notifications
You must be signed in to change notification settings - Fork 5
fix: validate enum values in nested models #163
Conversation
150fbb0
to
84d8b36
Compare
@@ -553,6 +553,20 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens | |||
} | |||
{{/required}} | |||
{{/isModel}} | |||
{{#isEnum}} | |||
{{#required}} |
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.
Should we have concerns about required readOnly and writeOnly schema properties?
(as called out for a similar change in metal-go)
equinix-labs/metal-go#132 (comment)
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.
This PR is making a small update to the validateJsonElement
section of the template, and the added code aligns with the validation that already exists for other properties.
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.
For reference/comparison, both this block and the subsequent isEnumRef
block are essentially copy-pastes of the preceding isModel
block: ddc37db#diff-f6e410ad0dea301581f6b3054b9f8fb2bcdb8f05807630eefbdddca891cd1371R544-R555
056d38f
to
ddc37db
Compare
{{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); | ||
{{/required}} | ||
{{^required}} | ||
// validate the optional field `{{{baseName}}}` | ||
if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { | ||
{{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); |
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.
This is, I think, the only difference between the isModel
block and the new enum blocks; through inspection of the template object I found that inline enums store the enum class name in datatypeWithEnum
, not in dataType
.
@@ -76,6 +77,11 @@ import com.google.gson.stream.JsonWriter; | |||
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); | |||
} | |||
} | |||
|
|||
public static void validateJsonElement(JsonElement jsonElement) throws IOException { |
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.
This is largely a copy-paste of the read
function above, modified to work with a JsonElement
rather than a JsonReader
: ddc37db#diff-e633e9a83ea415a1143582253f12897bcac9cda46fe610c6145443ab6e14ed2dR75-R78
@@ -71,6 +71,11 @@ | |||
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); | |||
} | |||
} | |||
|
|||
public static void validateJsonElement(JsonElement jsonElement) throws IOException { |
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.
This is largely a copy-paste of the read
function above, modified to work with a JsonElement
rather than a JsonReader
: ddc37db#diff-450b10b94dc0a9d1e3ca4b6aa10dcf879ce42fddf07d6704d95c203a0398ff4dR69-R73
Can we preserve this as a test? If https://github.com/equinix-labs/metal-java/tree/main/equinix-functional-test/src/test/java/com/equinix/test tests "functional" changes, perhaps a "behavioral" set of tests could be kept in the project to ensure that our patches and templates changes (work-arounds) behave as we expect. Approving as-is. We can open a new issue to address this. |
Is this a change that should be pushed upstream to openapitools-generator? |
Yes, this will be proposed upstream |
This PR is included in version 0.10.1 🎉 |
The Java generator for
openapi-generator
completely skips over enum validation in thevalidateJsonElement
function that is generated for each model class. As a result, enum values are validated inconsistently; if I have a modelX
that has a property that is an enum, the enum values will be validated if I am deserializing a JSON blob in which the top-level object is an instance ofX
, but the enum values will not be validated if I am deserializing a JSON blob that has an instance ofX
nested in it.This PR introduces custom templates so that we can add enum validation to
validateJsonElement
and ensure that enum values are validated even for nested models.We needed to modify two templates:
libraries/okhttp-gson/pojo.mustache
had to be updated to generate code that validates model properties that are enumsmodelEnum.mustache
andmodelInnerEnum.mustache
had to be updated to generate avalidateJsonElement
function for all enumsTemplate changes happen in this commit: ddc37db
Code is updated by the bot in this commit: b0f102a
This PR also includes an
example
that I used to replicate the validation issue and confirm that my tests fixed it; I intended to remove it before merge, since it's really not an example of how the SDK should be used, but I'm open to keeping it. In the meantime, at least, this PR can be poked at by checking it out locally and running these commands in the project root: