modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml can be used to reproduce this.nullable, null is never sent.The problem is very similar to what was described in [1] - if an attribute is marked as nullable in the OpenAPI spec, it's not actually possible to send a null value in a POST/PUT request for it (using okhttp/gson client, but AFAICS other clients would have these issues as well).
4.0.2, but the issue seems to always have been there.
modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
openapi-generator -g java -i modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml -o /tmp/petstore/
You just need to generate a Java client for OpenAPI spec that has any nullable attributes and see that it doesn't really send nulls for them in the request JSON objects.
[1] https://github.com/OpenAPITools/openapi-generator/issues/522
[2] https://github.com/OpenAPITools/openapi-generator/pull/3371
My solution for Go from [2], which I believe is correct, considers 4 different states for every attribute:
All these 4 states need to be covered properly in order to be able to send the requests correctly according to the spec. Here's my thinking on how the 4 above scenarios should behave:
null value is explicit or not; if this flag is true and the attribute is null, it would get serialized as null; if this flag is false and the attribute is null, it wouldn't get serialized at allI propose that an {{name}}isExplicitNull attribute is added to the POJO class for every nullable attribute (defaultin to false as well as set{{name}}IsExplicitNull and is{{name}}ExplicitNull setter/getter. In addition to that, we'd need to add custom serialization logic that would respect these "explicit null flags" to properly serialize the request.
I'm also fairly certain that this can be done as a backwards compatible change, since it will only be adding things, not removing or changing the current API of the generated classes.
馃憤 Thanks for opening this issue!
馃彿 I have applied any labels matching special text in your issue.
The team will review the labels and make any necessary changes.
Ok, so a potential way to go forward that I can see:
I will be detailing this out using jackson, since it seems to me that it would make it easier to implement than gson.
Scenario 4 (from the original issue report) is easy to solve, just mark the variable with @JsonInclude(JsonInclude.Include.ALWAYS).
Scenario 3 is a little bit complicated, but I think it could be solved like this:
java.util.Optional - we can't use that java.util.Optional, as we want to support older Java versions (or maybe there's a library out there that implements this for older Java versions, I would have to see if that's the case).getOptional{{name}}, which would return the Optional object. This would allow users to find out whether or not the API response contained explicit null or not.JSON.mustache that would know how to serialize Optional:null (through calling the setter with null), the field would get serialized as null.Deserialization should work out-of-the-box, since (IIUC) the setter is called if (and only if) the field is in the API response. Hence if the field is not in the API response, setter won't be called and the Optional will be "empty" (=> so even followup serialization of the same object will still work ok).
Does that make sense? I think this is easy enough that I could send a PR myself to implement it (for jackson).
* Create a simple equivalent of `java.util.Optional` - we can't use that `java.util.Optional`, as we want to support older Java versions (or maybe there's a library out there that implements this for older Java versions, I would have to see if that's the case).
Phew, that would be (in my opinion) really ugly to create a new Optional. I would go as far as saying it is an 8+ feature only since older java versions are no longer officially supported I would not bother with making something ugly just to support some unsupported language versions.
The Idea of using a Monad to box the optional null sounds nice. The problem I see with this solution: Some people falsely assume that Optional adds some sort of null safety because an Optional can never be null *cough*. To make it clear to everyone I would only vote for that feature if all Optionals would be annotated with @Nullable. That's the problem programming in java, a language with a lot of promises, guesses and no Type-Safety (Nulltypes) :D
One big issue not using Optional is that Optional is a final class without an interface so all methods which are working with the Java-Implementation wouldn't work with the new implemented Optional.
On the other hand there is already another Optional in one of the dependencies (com.google.common.base.Optional
In the Spring codegen, we use a custom wrapper called JsonNullable which can have the three states: absent, present and null, present and non-null (where Optional can only have 2 states: empty or present).
I suggest to use it for the java clients also. See https://github.com/OpenAPITools/jackson-databind-nullable for documentation on JsonNullable
@cbornet looks nice! I'll try to swap it for the simple implementation that I did in my PR #3474, it looks like it could make it simpler.