Skip to content

Discriminator in Open API JSON Causes "Type expected" Error w/RTK Query Code Gen #4791

Open
@fuzl-llc

Description

@fuzl-llc

I have an API and use NSwag.AspNetCore to generate open api JSON. I have a "WidgetBase" abstract type with several derived types that are distinquished by a WidgetType property. The generated JSON used to be this:

      "WidgetBase": {
        "type": "object",
        "x-abstract": true,
        "additionalProperties": false,
        "properties": {
          "widgetType": {
            "type": "string"
          }
        }
      }

With the above, RTK Query Code Gen runs perfectly fine.

I updated to a newer version of NSwag and it now adds some additional info (discriminator, required/$type, and properties/$type):

      "WidgetBase": {
          "type": "object",
          "discriminator": {
              "propertyName": "$type"
          },
          "x-abstract": true,
          "additionalProperties": false,
          "required": [
              "$type"
          ],
          "properties": {
              "widgetType": {
                  "type": "string"
              },
              "$type": {
                  "type": "string"
              }
          }
      }

Now when I run RTK Query Code Gen, I get this error:

Generating ./fuzlApiTypes.ts
SyntaxError: Type expected. (152:26)
�[0m �[90m 150 |�[39m     errorMessage�[33m?�[39m�[33m:�[39m string�[33m;�[39m
 �[90m 151 |�[39m }�[33m;�[39m
�[31m�[1m>�[22m�[39m�[90m 152 |�[39m �[36mexport�[39m type �[33mWidgetBase�[39m �[33m=�[39m �[33m;�[39m
 �[90m     |�[39m                          �[31m�[1m^�[22m�[39m
 �[90m 153 |�[39m �[36mexport�[39m type �[33mWidgetDrawer�[39m �[33m=�[39m {
 �[90m 154 |�[39m     widgets�[33m?�[39m�[33m:�[39m �[33mWidgetBase�[39m[]�[33m;�[39m
 �[90m 155 |�[39m }�[33m;�[39m�[0m
    at _4 (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:17:70560)
    at N4 (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:20:955)
    at Object.M4 [as parse] (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:20:1477)
    at parse5 (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/index.mjs:19838:24)
    at coreFormat (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/index.mjs:20386:25)
    at formatWithCursor (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/index.mjs:20598:14)
    at Object.format2 (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/index.mjs:22002:25)
    at generateEndpoints (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/@rtk-query/codegen-openapi/src/index.ts:25:7)
    at v (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/@rtk-query/codegen-openapi/src/bin/cli.ts:59:7) {
  loc: { start: { line: 152, column: 26 }, end: { line: 152, column: 26 } },
  cause: $f: Type expected.
      at ed (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:17:8588)
      at ad (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:17:10524)
      at Xh (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:17:65505)
      at a4 (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:17:70421)
      at l0 (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:17:70163)
      at file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:20:1441
      at s4 (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:17:70714)
      at Object.M4 [as parse] (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/plugins/typescript.mjs:20:1425)
      at parse5 (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/index.mjs:19838:24)
      at coreFormat (file:///C:/Dev/Code/Fuzl/Apps/client/node_modules/prettier/index.mjs:20386:25) {
    fileName: 'estree.ts',
    location: { end: [Object], start: [Object] }
  },
  codeFrame: '\x1B[0m \x1B[90m 150 |\x1B[39m     errorMessage\x1B[33m?\x1B[39m\x1B[33m:\x1B[39m string\x1B[33m;\x1B[39m\n' +
    ' \x1B[90m 151 |\x1B[39m }\x1B[33m;\x1B[39m\n' +
    '\x1B[31m\x1B[1m>\x1B[22m\x1B[39m\x1B[90m 152 |\x1B[39m \x1B[36mexport\x1B[39m type \x1B[33mWidgetBase\x1B[39m \x1B[33m=\x1B[39m \x1B[33m;\x1B[39m\n' +
    ' \x1B[90m     |\x1B[39m                          \x1B[31m\x1B[1m^\x1B[22m\x1B[39m\n' +
    ' \x1B[90m 153 |\x1B[39m \x1B[36mexport\x1B[39m type \x1B[33mWidgetDrawer\x1B[39m \x1B[33m=\x1B[39m {\n' +
    ' \x1B[90m 154 |\x1B[39m     widgets\x1B[33m?\x1B[39m\x1B[33m:\x1B[39m \x1B[33mWidgetBase\x1B[39m[]\x1B[33m;\x1B[39m\n' +
    ' \x1B[90m 155 |\x1B[39m }\x1B[33m;\x1B[39m\x1B[0m'
}

I can't make much sense of this but see "SyntaxError: Type expected" and "WidgetBase" mentioned. The JSON seems to indicate that I have a "type" property on WidgetBase which I do not so I tried to make discriminator/propertyName referernce the widgetType property by adding JsonPolymorphicAttribute to my WidgetBase type in the C# code:

    [JsonPolymorphic(TypeDiscriminatorPropertyName = "widgetType")]
    [JsonDerivedType(typeof(Widget2))]
    [JsonDerivedType(typeof(Widget2))]
    public abstract class WidgetBase
    {
        public string WidgetType { get; set; } = String.Empty;
    }

That then resulted in this, seemingly better, JSON that correctly says that "widgetType" is the thing that can be used to discriminate between derived types:

      "WidgetBase": {
        "type": "object",
        "discriminator": {
          "propertyName": "widgetType"
        },
        "x-abstract": true,
        "additionalProperties": false,
        "required": [
          "widgetType"
        ],
        "properties": {
          "widgetType": {
            "type": "string"
          }
        }
      }

This seemed better since the WidgetBase type does have a WidgetType property. That property is Pascal case in C# and camel case in the generated client code and I tried both for the JsonPolymorphicAttribute just in case but either way I get basically the same error when I try to generate code with the RTK Query Code Gen.

Does RTK Query Code Gen support this discriminator value? I could be doing something wrong, but it seems to break when nothing really changes except adding the extra discriminator and related JSON to the API spec.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions