oneOf is not produce the right results for C# generated classes?
See original GitHub issueWhen trying to generate an API client for ShipEngine, NSwag is having issues when using oneOf to combine related entities to indicate that the request can have one of the two values. It ends up just bringing in the type for the first value, but the second is never included. Here is the simplified yaml file:
openapi: 3.0.0
info:
title: oneOf bug
version: 1.0
components:
schemas:
se_id:
title: se_id
type: string
calculate_rates_request_body:
title: calculate_rates_request_body
type: object
required:
- shipment_id
- shipment
additionalProperties: false
oneOf:
- $ref: '#/components/schemas/shipment_id_request'
- $ref: '#/components/schemas/shipment_request'
shipment_id_request:
title: shipment_id_request
type: object
additionalProperties: false
properties:
shipment_id:
allOf:
- $ref: '#/components/schemas/se_id'
shipment_request:
title: shipment_request
type: object
additionalProperties: false
properties:
shipment:
allOf:
- $ref: '#/components/schemas/address_validating_shipment'
address_validating_shipment:
title: address_validating_shipment
type: object
required:
- shipment_id
- carrier_id
additionalProperties: false
properties:
shipment_id:
allOf:
- $ref: '#/components/schemas/se_id'
carrier_id:
allOf:
- $ref: '#/components/schemas/se_id'
The C# class generated is the following. Note that the it only contains the base ShipmentId field, and not the second Shipment field which the schema happily supports.
public partial class CalculateRatesRequestBody
{
public string ShipmentId { get; set; }
}
public partial class ShipmentRequest
{
public AddressValidatingShipment Shipment { get; set; }
}
public partial class AddressValidatingShipment
{
public string ShipmentId { get; set; }
public string CarrierId { get; set; }
}
What I would have expected to be generated is the following:
public partial class CalculateRatesRequestBody
{
public string ShipmentId { get; set; }
public AddressValidatingShipment Shipment { get; set; }
}
public partial class AddressValidatingShipment
{
public string ShipmentId { get; set; }
public string CarrierId { get; set; }
}
If I change it to be allOf rather than oneOf, I get the following which does work. But in reality the spec is correct in saying it’s a oneOf and not allOf, because only one can be sent in the request at a time, not all of them:
public partial class CalculateRatesRequestBody : ShipmentIdRequest
{
}
public partial class ShipmentIdRequest
{
public string ShipmentId { get; set; }
}
public partial class ShipmentRequest
{
public AddressValidatingShipment Shipment { get; set; }
}
public partial class AddressValidatingShipment
{
public string ShipmentId { get; set; }
public string CarrierId { get; set; }
}
So it seems to me when generating a C# class for this specification, we should really be generating the same schema as the allOf case. Any ideas on the best way to fix this in the code? I assume it’s probably in the JsonSchema rendering code, not NSwag itself?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:6
- Comments:33 (14 by maintainers)
oneOf can be accomodated by polymorphism. From what I understood here allOf is already supported. anyOf could be potentially supported the same way as oneOf with polymorphism with having different requirements for each class while they are also merged together, but having a validation logic would seem better at that point.
Isn’t this pretty major issue if NSwag doesn’t really work properly with the standard? Can this issue get a bit more traction?
We eventually figured out that openapi-generator can generate working code from
oneOf
elements. It took a couple of days to bump into the right parameters on a revisit (they were a bit hidden in the documentation). Our guy usednetcore
generator with atargetFramework
ofnet4.7
and all was well.I also realized that this stackoverflow answer (“replace the oneOf with a reference to an abstract type”) was a viable workaround that might work with generators like this one (it did with openapi-generator java generator).