-
Notifications
You must be signed in to change notification settings - Fork 166
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
Populate the discriminator property for derrived types. #4618
Comments
Hi @greg-ww |
The request body takes an array of a base type, the base type has a discriminator mapping similar to below.
|
These values appear to be used in the generated code for deserializing the models but not when serializing them. I was wondering if this is an intentional design choice. |
Any chance you can share the schema of the derive type? Ideally, the microsoft.graph.managedIOSLobApp:
allOf:
- $ref: '#/components/schemas/microsoft.graph.managedMobileLobApp'
- title: managedIOSLobApp
required:
- '@odata.type'
type: object
properties:
....
....
'@odata.type':
type: string
default: '#microsoft.graph.managedIOSLobApp'
description: Contains properties and inherited properties for Managed iOS Line Of Business apps.
x-ms-discriminator-value: '#microsoft.graph.managedIOSLobApp' The code generated would then have it set in the constructor similar to |
I was kind of hoping this could be treated as a serialization concern in C#. When you deserialize a list of a base type you use the discriminator mapping to determine the derived type to use, when serializing to a list of a base type you set the discriminator value based on the mapping. Would save people having to add stuff to their Open API spec just to get the discriminator to work automatically when all the information needed is in the mapping. |
I also found some other issues while looking for a work around for this. In .Net setting a default value works but to support type narrowing in TS we wanted the discriminator value to be hard coded on the derived types. (For context the typescript team I am supporting isn't using Kiota as their generator). Since OpenAPI.NET(https://github.com/microsoft/OpenAPI.NET) doesn't yet support const values I settled for defining the discriminator property as having an enum with only one type. This works well for the typescript clients giving them a hard coded value. However in the .Net client I generate with kiota the single value enum appears to have to effect at all, it would be great if this also hard coded the value. Should I make another issue for this request? Additionally to work around this I tried adding both a default value to support the Kiota .Net client and an enum with only one value for the TS client, unfortunately this generates code that doesn't compile. Weirdly giving it a default value that matches the only value in the enum makes it try to assign an enum type to my string discriminator property. Should I make another issue for this also? I can provide simplified example open api specs in json that show case these two other issues. |
|
I believe the issue here is that the base has a type that is a string while the derived instances have the enum declaration. This causes a conflict by setting set the default as an enum while the type information from the base is a string. |
Am I mistaken in thinking that restricting the values for inherited properties in derived types using "enum" is valid in the Open API spec? |
As the property is defined in the base type and redefined in the derived type, the type of the base would be a string while the derived types would have the properties be inferred to be enums. Furthermore, since the schemas are inlined, Kiota would generate different enum types models for each derived type property which would conflict and cause an error. You would need to have consistency in the typing down the inheritance by either.
{
"openapi": "3.0.0",
"info": {
"title": "Polymorphic API",
"version": "1.0.0"
},
"paths": {
"/polymorphic-list": {
"post": {
"summary": "Accepts a list of polymorphic types and returns a list",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/BaseType"
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/BaseType"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"BaseType": {
"type": "object",
"properties": {
"$type": {
"$ref": "#/components/schemas/TypeValues"
}
},
"required": ["$type"],
"discriminator": {
"propertyName": "$type",
"mapping": {
"A": "#/components/schemas/A",
"B": "#/components/schemas/B"
}
}
},
"A": {
"allOf": [
{ "$ref": "#/components/schemas/BaseType" },
{
"type": "object",
"properties": {
"$type": {
"$ref": "#/components/schemas/TypeValues"
}
},
"required": ["$type"]
}
]
},
"B": {
"allOf": [
{ "$ref": "#/components/schemas/BaseType" },
{
"type": "object",
"properties": {
"$type": {
"$ref": "#/components/schemas/TypeValues"
}
},
"required": ["$type"]
}
]
},
"TypeValues":{
"type": "string",
"enum": ["onlyValue", "alternativeValue"],
"default": "onlyValue"
}
}
}
}
|
@andrueastman You seem to be explaining how Kiota does not support this use case, I am more interested in discussion of if it should support it. Enums are not types in the OpenAPI spec, I do not believe there is anything inconsistent about the typing of my property in OpenAPI. I am under the impression that my spec is valid (although admittedly not designed with the sole focus of making Kiota generate compiling code). If my spec is valid (in the eyes of OpenAPI) should Kiota be able to support it? |
@greg-ww Thanks for raising this issue and providing the details. I have a few thoughts.
@andrueastman What do you think about special casing enums with one value to be a const of the type defined in the schema? That would avoid the problem you describe of base classes redefining the type in derived classes. |
Is your feature request related to a problem? Please describe the problem.
I could be doing something wrong here but I couldn't find any documentation on sending heterogeneous collections in a post, only on receiving them. I have an endpoint that takes a list of derived types, the open API spec defines the discriminator property and the mappings for the derived types. The models for the derived types that Kiota generates have a Type property I can assign the correct value to but by default it is empty.
Client library/SDK language
Csharp
Describe the solution you'd like
Since the desired value for these types is constant and defined in the open API spec I don't understand why I need to set it when working with these models. Can it not just be hard coded to the correct value?
Additional context
It's possible there is something wrong with my open API spec but I couldn't find any confirmation in the documentation of what the desired behavior is for this use case is.
The text was updated successfully, but these errors were encountered: