C# How to handle polymorphic models using NSwag
Asked Answered
R

2

11

I have a polymorphic model:

public class CreateOrderRequest
{
    public List<CreateOrderItem> OrderItems { get; set; } 
}

/// <summary>
/// Identifies a new item within an order
/// </summary>    
[JsonConverter(typeof(CreateOrderLineJsonConvertor))]
[KnownType("GetKnownTypes")]
public class CreateOrderItem
{
    public string OrderContext { get; set; }
    public string OrderItemType { get; set; }

    public static Type[] GetKnownTypes()
    {
        return new[]
        {
            typeof(OrderItemType1), typeof(OrderItemType2)
        };
    }
}

public class OrderItemType1: CreateOrderItem
{
     public string Type1Prop {get;set;}
}

public class OrderItemType2: CreateOrderItem
{
     public string Type2Prop {get;set;}
}

Using NSwag (NSwag.AspNetCore) according to the documentation, I expected this to be enough so that documentation indicated / contained the order item types? But no...

enter image description here

Have i completely missed the point of what NSwag requires? I have the OrderItemType property. Do i need to get a discriminator involved? Where is this documented?

TIA

Rapt answered 4/9, 2017 at 22:42 Comment(0)
A
8

You need

[JsonConverter(typeof(JsonInheritanceConverter), "discriminator")]

on the base class so that the discriminator is added.

See https://github.com/RSuter/NJsonSchema/wiki/Inheritance

Assoil answered 5/9, 2017 at 6:26 Comment(8)
Thanks Rico. Possibly dumb question. This is an aspnet core web api application. Do i read the linked doc correctly that the attribute enables correct swagger behaviour and deserialization in generated clients ... but i cannot remove the existing base class attribute required for the server to deserialize requests? (Sry, cannot test from my current location)Rapt
NSwag (or NJS) looks for this converter (the name) and only if its available the correct schema is generated. Additionally the converter adds the discriminator property to the json so that deserializing is working correctly...Assoil
And btw: The served swagger ui 2.x does not support discriminators, maybe you have to use an own newer version or redocAssoil
Didn't work for me. The generated C# class doesn't contain the inherited types.Quittance
You also need to add KnownType attributes, and generate the spec and code with NSwagAssoil
@RicoSuter So question, I have an abstract base class called ResultRecord. I have seven "KnownType" attributes and I have also specified [JsonConverter(typeof(JsonInheritanceConverter), "discriminator")] as specified above. When I generate the code, I don't see all the properties of the descendant objects flattened into ResultRecord. Instead, I see a bunch of JsonInheritanceAttribute attributes which indicate the hierarchy. Is there a way to achieve what I'm trying to achieve?Quittance
Maybe this github.com/RicoSuter/NJsonSchema/blob/master/src/NJsonSchema/…Assoil
But if you have multille concrete types then flatten wont work. You need inheritanceAssoil
P
0

I used the answer by Rico Suiter as a starting point. JSON objects got correct discriminator field, but polymorphic description was missing from swagger.json contract.

Swagger annotations to fix the issue:

[JsonConverter(typeof(JsonInheritanceConverter), "discriminator")]
[SwaggerDiscriminator("discriminator")]
[SwaggerSubType(typeof(ChildDto1))]
[SwaggerSubType(typeof(ChildDto2))]
[SwaggerSubType(typeof(ChildDto3))]
public abstract class BaseDto
{
    public int BaseProperty { get; set; }
}

Also turned on annotations in Startup.cs:

services.AddSwaggerGen(c =>
{
    c.EnableAnnotations(true, true);
    ...
}

Used Swashbuckle.AspNetCore.Annotations v6.1.0 package

Prehistory answered 10/1 at 12:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.