-
-
Notifications
You must be signed in to change notification settings - Fork 6.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue #10593 Fix nullable property implemented with oneOf construct #10602
Issue #10593 Fix nullable property implemented with oneOf construct #10602
Conversation
dccc2c1
to
cb848b3
Compare
cb848b3
to
fd37884
Compare
@@ -846,7 +846,7 @@ export type Fruit = Apple | Banana; | |||
* @type FruitReq | |||
* @export | |||
*/ | |||
export type FruitReq = AppleReq | BananaReq | Null; | |||
export type FruitReq = AppleReq | BananaReq | null; |
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.
Look like we fixed some bug here too
* @param nonNullableProperty | ||
*/ | ||
|
||
data class ModelWithNullableObjectProperty ( |
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 what we tried to achieve : val propertyName31: PropertyType? = null,
* @export | ||
* @interface ModelWithNullableObjectProperty | ||
*/ | ||
export interface ModelWithNullableObjectProperty { |
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.
here the fix for typescript
}) | ||
@javax.annotation.processing.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") | ||
public class ModelWithNullableObjectProperty { | ||
public static final String JSON_PROPERTY_PROPERTY_NAME30 = "propertyName30"; |
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.
Here is the result for java
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.
Thanks for your contribution!
I haven't even realized nullable was so broken :)
@@ -2092,6 +2092,10 @@ public String toAnyOfName(List<String> names, ComposedSchema composedSchema) { | |||
* Otherwise, a name is constructed by creating a comma-separated list of all the names | |||
* of the oneOf schemas. | |||
* | |||
* If the oneOf schema contains only one element and have the openapi 3.0 nullable flag, | |||
* or one element and the openapi 3.1 'null' type, only this element is returned. |
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.
how about the case with more than one type in oneOf?
oneOf:
- 'null'
- ref: ModelA
- ref: ModelB
How do we handle this?
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.
I didn't change that one, it will behave like before.
Since many language plugin does not seen to really support oneOf, it will still be broken.
I think typescript will be ok and produce ModelA | Model B | null
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.
Do you think it's worth adding to the test spec and see what the generated typescript code looks like?
The reason I'm specifically curious about it is that you seem to filter out the "null" part of the union. And I'm not sure whether it still preserves in some flags and resurfaces later
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.
I added a case in the yaml. We can see the result in this commit :
9b9f58659cefc284e9a4c0ce3c361c8c404d2292
export interface ModelWithNullableObjectProperty { | ||
/** | ||
* | ||
* @type {PropertyType} |
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.
@type
annotation is no longer correct (should be PropertyType | null
).
honestly, I don't know why it's needed anyway, in the presence of the real type definitions.
but if it's there and not in sync with the actual type, I'm concerned it might confuse some tools/IDEs.
Any thoughts?
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.
Humm, I did not change the templates, but if you want my personal advice, I would remove the @type
. Not in this pr of course.
|
||
'propertyName30': PropertyTypeToJSON(value.propertyName30), | ||
'propertyName31': PropertyTypeToJSON(value.propertyName31), | ||
'nonNullableProperty': string | numberToJSON(value.nonNullableProperty), |
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.
broken typescript code
it doesn't mean it's a regression - maybe we never had a similar case in the samples, and it's been always effectively broken. but need to verify
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.
Indeed, this is weird. I added this property int the last minute to check non-regression on my unit tests and did not check the generated code.
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.
The template takes the dataType as is whish is string | number
I think is is indeed not a regression.
'{{baseName}}': {{datatype}}ToJSON(value.{{name}}),
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.
yep, you're right! I just recalled it getting surfaced in another PR earlier: #10017 (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 won't be trivial to fix. I think it should be documented in another issue.
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.
Absolutely. I just wanted to double check it's not something we're breaking in this PR - that's it :)
// Non regression on regular oneOf construct | ||
propertyName = "nonNullableProperty"; | ||
property = codegen.fromProperty(propertyName, (Schema) schema.getProperties().get(propertyName)); | ||
assertEquals(property.openApiType, "string | number"); |
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.
so for regular non-nullable oneOf
we produce e.g string | number
.
why do we need different handling for null
? I feel if it could be string | null
, we would have more consistent templates / generated code. for typescript, at least
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.
| null
is somehow added later in the process.
It's not very easy to navigate this code, not all language plugin are made in a consistant way and some things that could have been handled in the DefaultCodegen looks hacked in some languages.
The post-precessing process is not all clear to me. Also it's not clear how to apply it in unit tests.
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.
Looks good from my standpoint (typescript).
I didn't look closely into java/kotlin generators output though.
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.
Agree with @amakhrov - TypeScript looks good from my perspective as well.
9b9f586
to
db24b68
Compare
* @var string[] | ||
*/ | ||
protected static $openAPITypes = [ | ||
'property_name30' => 'PropertyType', |
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.
We just noticed that we still have a problem for PHP.
This name must be typed with namespaces for ObjectSerializer to be able to handle it
Just updated this branch with master. I will put it on hold until I fix PHP serialization |
PHP namespaces are now fixed. This pr is ready for re-review. |
a90fa57
to
b795909
Compare
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.
forgot to submit these comments days ago
return $this; | ||
} | ||
|
||
/** |
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.
Regular non-nullable oneOf properties are not handled by this PR. It's normal to still get strange types for the two following properties
* @template TKey int|null | ||
* @template TValue mixed|null | ||
*/ | ||
class ModelWithNullableObjectProperty implements ModelInterface, ArrayAccess, \JsonSerializable |
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.
Begin of the interesting part for PHP
1ba7bc9
to
81ff959
Compare
I just updated this pr on master (6.0.0) and some of my fixes does not work anymore. I could trace it to a big refacor on inline schema resolver done in #12104 I also noticed some weird stuff with 6.0.0 on some of our generated sdks. This is not relate to this pr, but you can notice the diff on ma last commit f4043c9 there is a new model generated from one of the inline field :
I can file a new issue for that, but for this pr I would like your advice on the best way I could handle nullable oneOf with your new resolver. Regards, |
81ff959
to
f4043c9
Compare
6f22b61
to
1e54f0f
Compare
1e54f0f
to
7dee4c1
Compare
@wing328 I managed to make my nullable fixes work again 7dee4c1 There are still some generated types from oneOf or anyOf but I think it was intended. For exemple a
|
Most of the features introduced by this pull request are now available in the 7.1 branch. The only case that did not work for us was the
I was able to fix it in the OpenAPI Normalizer |
See issue #10593
PR checklist
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example
./bin/generate-samples.sh bin/configs/java*
.For Windows users, please run the script in Git BASH.
master
(5.3.0),6.0.x
Typescript
@TiFu (2017/07) @taxpon (2017/07) @sebastianhaas (2017/07) @kenisteward (2017/07) @Vrolijkx (2017/09) @macjohnny (2018/01) @topce (2018/10) @akehir (2019/07) @petejohansonxo (2019/11) @amakhrov (2020/02)
Kotlin
@jimschubert (2017/09) heart, @dr4ke616 (2018/08) @karismann (2019/03) @Zomzog (2019/04) @andrewemery (2019/10) @4brunu (2019/11) @yutaka0m (2020/03)
PHP
@jebentier (2017/07), @dkarlovi (2017/07), @mandrean (2017/08), @jfastnacht (2017/09), @ackintosh (2017/09) heart, @ybelenko (2018/07), @renepardon (2018/12)
Java
@bbdouglas (2017/07) @sreeshas (2017/08) @jfiala (2017/08) @lukoyanov (2017/09) @cbornet (2017/09) @jeff9finger (2018/01) @karismann (2019/03) @Zomzog (2019/04) @lwlee2608 (2019/10) @nmuesch (2021/01)