Skip to content

Polymorphic deserialization 'broken' with more than one level of inheritance (C#) #2430

Closed

Description

The problem is basically this: given the following definitions:

"ResponseBase": {
      "discriminator": "_type",
      "type": "object",
      "required": [
        "_type"
      ],
      "properties": {
        "_type": {
          "type": "string"
        }
      }
    },

    "Identifiable": {
      "allOf": [
        {
          "$ref": "#/definitions/ResponseBase"
        },
        {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            }
          }
        }
      ]
    },
    "Response": {
      "allOf": [
        {
          "$ref": "#/definitions/Identifiable"
        },
        {
          "type": "object",
          "properties": {
            "instrumentation": {
              "$ref": "#/definitions/Instrumentation"
            },
          }
        }
      ]
    },

There is no (apparent) way to generate code that allows the generated client to ever return the "Response" class during deserialization. The same discriminator ("_type") is used to return either the class names 'Identifiable' or 'Response', depending on what the server decides to create. In the generated client, the only PolymorphicDeserializeJsonConverter on "_type" is created just for ResponseBase, not for Identifiable. This means if we have another schema that declares Identifiable as the base type, but the server actually returns a Response object (with _type = Response), the json deserialization will end up defaulting to the Identifiable object.

Simply duplicating the _type property as well as the discriminator: _type into the Identifiable schema doesn't work, since apparently there is some intelligent filtering in the generator to prevent duplicate property declarations. However, this means that in the SchemaBuilder.cs, nothing will ever set the PolymorphicDiscriminator property (it needs to be the same between some seen property [not including parent properties] and a seen discriminator), which means when generating thge service client in ServiceClientTemplate.cshtml, no converters will be added for Identifiable since IsPolymorphic is false.

If there's a way to support this that I'm missing, that would be great; otherwise, would appreciate an option to use BaseIsPolymorphic instead of IsPolymorphic in the client template (although that would include all the leaf nodes of our complex, schema.org based inheritance tree, which gets wasteful at the number of schemas we have).

We solved this with the default swagger generator by using a serialization binder instead (as part of the Serialization/DeserializationSettings), so that we wouldn't have to instantiate a new converter for each of our polymorphic types (we have about ~400 schemas). If support for a binder is on your radar, that would be wonderful.

So far this is the only quirk I've encountered that I can't seem to bypass; still, autorest seems very useful for us.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions