question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] [dart-dio-next] Models inside anyOf missing type information

See original GitHub issue

Bug Report Checklist

  • [x ] Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • [x ] Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What’s the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

When a model has a parameter of type allOf with only one child type, specific type information about that type is lost and it is parsed as a generic model.

For example if we have a model User with a field type, which is defined as allOf and then a inner type enum:

      "User": {
        "type": "object",
        "properties": {
          "type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/UserType"
              }
            ],
            "description": "type of user"
          }
        }
      },
      "UserType": {
        "type": "string",
        "title": "UserType",
        "enum": [
          "admin",
          "user"
        ]
      }

The model definition of UserType below has "isEnum": true, but the variable/field definition of UserType in User model definition has "isEnum": false and "isModel": true.

This model is an enum and `“isEnum” should always be true.

Debug model output ``` [ { "importPath": "lib.src.model.User", "model": { "anyOf": [], "oneOf": [], "allOf": [], "anyOfProps": [], "allOfProps": [], "oneOfProps": [], "name": "User", "classname": "User", "classVarName": "user", "modelJson": "{\n \"type\" : \"object\",\n \"properties\" : {\n \"type\" : {\n \"description\" : \"type of user\",\n \"allOf\" : [ {\n \"$ref\" : \"#/components/schemas/UserType\"\n } ]\n }\n }\n}", "dataType": "JsonObject", "classFilename": "user", "isAlias": false, "isString": false, "isInteger": false, "isLong": false, "isNumber": false, "isNumeric": false, "isFloat": false, "isDouble": false, "isDate": false, "isDateTime": false, "isShort": false, "isUnboundedInteger": false, "isBoolean": false, "additionalPropertiesIsAnyType": false, "vars": [ { "openApiType": "UserType", "baseName": "type", "complexType": "UserType", "getter": "getType", "setter": "setType", "description": "type of user", "dataType": "UserType", "datatypeWithEnum": "UserType", "name": "type", "defaultValueWithParam": " = data.type;", "baseType": "UserType", "unescapedDescription": "type of user", "example": "null", "jsonSchema": "{\n \"description\" : \"type of user\",\n \"allOf\" : [ {\n \"$ref\" : \"#/components/schemas/UserType\"\n } ]\n}", "exclusiveMinimum": false, "exclusiveMaximum": false, "required": false, "deprecated": false, "hasMoreNonReadOnly": false, "isPrimitiveType": false, "isModel": true, "isContainer": false, "isString": false, "isNumeric": false, "isInteger": false, "isShort": false, "isLong": false, "isUnboundedInteger": false, "isNumber": false, "isFloat": false, "isDouble": false, "isDecimal": false, "isByteArray": false, "isBinary": false, "isFile": false, "isBoolean": false, "isDate": false, "isDateTime": false, "isUuid": false, "isUri": false, "isEmail": false, "isNull": false, "isFreeFormObject": false, "isAnyType": true, "isArray": false, "isMap": false, "isEnum": false, "isReadOnly": false, "isWriteOnly": false, "isNullable": true, "isSelfReference": false, "isCircularReference": false, "isDiscriminator": false, "vars": [], "requiredVars": [], "vendorExtensions": { "x-index": 1 }, "hasValidation": false, "isInherited": false, "nameInCamelCase": "Type", "nameInSnakeCase": "TYPE", "uniqueItems": false, "isXmlAttribute": false, "isXmlWrapped": false, "additionalPropertiesIsAnyType": false, "hasVars": false, "hasRequired": false, "hasDiscriminatorWithNonEmptyMapping": false, "datatype": "UserType", "iexclusiveMaximum": false } ], "allVars": [ { "openApiType": "UserType", "baseName": "type", "complexType": "UserType", "getter": "getType", "setter": "setType", "description": "type of user", "dataType": "UserType", "datatypeWithEnum": "UserType", "name": "type", "defaultValueWithParam": " = data.type;", "baseType": "UserType", "unescapedDescription": "type of user", "example": "null", "jsonSchema": "{\n \"description\" : \"type of user\",\n \"allOf\" : [ {\n \"$ref\" : \"#/components/schemas/UserType\"\n } ]\n}", "exclusiveMinimum": false, "exclusiveMaximum": false, "required": false, "deprecated": false, "hasMoreNonReadOnly": false, "isPrimitiveType": false, "isModel": true, "isContainer": false, "isString": false, "isNumeric": false, "isInteger": false, "isShort": false, "isLong": false, "isUnboundedInteger": false, "isNumber": false, "isFloat": false, "isDouble": false, "isDecimal": false, "isByteArray": false, "isBinary": false, "isFile": false, "isBoolean": false, "isDate": false, "isDateTime": false, "isUuid": false, "isUri": false, "isEmail": false, "isNull": false, "isFreeFormObject": false, "isAnyType": true, "isArray": false, "isMap": false, "isEnum": false, "isReadOnly": false, "isWriteOnly": false, "isNullable": true, "isSelfReference": false, "isCircularReference": false, "isDiscriminator": false, "vars": [], "requiredVars": [], "vendorExtensions": { "x-index": 1 }, "hasValidation": false, "isInherited": false, "nameInCamelCase": "Type", "nameInSnakeCase": "TYPE", "uniqueItems": false, "isXmlAttribute": false, "isXmlWrapped": false, "additionalPropertiesIsAnyType": false, "hasVars": false, "hasRequired": false, "hasDiscriminatorWithNonEmptyMapping": false, "datatype": "UserType", "iexclusiveMaximum": false } ], "requiredVars": [], "optionalVars": [ { "openApiType": "UserType", "baseName": "type", "complexType": "UserType", "getter": "getType", "setter": "setType", "description": "type of user", "dataType": "UserType", "datatypeWithEnum": "UserType", "name": "type", "defaultValueWithParam": " = data.type;", "baseType": "UserType", "unescapedDescription": "type of user", "example": "null", "jsonSchema": "{\n \"description\" : \"type of user\",\n \"allOf\" : [ {\n \"$ref\" : \"#/components/schemas/UserType\"\n } ]\n}", "exclusiveMinimum": false, "exclusiveMaximum": false, "required": false, "deprecated": false, "hasMoreNonReadOnly": false, "isPrimitiveType": false, "isModel": true, "isContainer": false, "isString": false, "isNumeric": false, "isInteger": false, "isShort": false, "isLong": false, "isUnboundedInteger": false, "isNumber": false, "isFloat": false, "isDouble": false, "isDecimal": false, "isByteArray": false, "isBinary": false, "isFile": false, "isBoolean": false, "isDate": false, "isDateTime": false, "isUuid": false, "isUri": false, "isEmail": false, "isNull": false, "isFreeFormObject": false, "isAnyType": true, "isArray": false, "isMap": false, "isEnum": false, "isReadOnly": false, "isWriteOnly": false, "isNullable": true, "isSelfReference": false, "isCircularReference": false, "isDiscriminator": false, "vars": [], "requiredVars": [], "vendorExtensions": {}, "hasValidation": false, "isInherited": false, "nameInCamelCase": "Type", "nameInSnakeCase": "TYPE", "uniqueItems": false, "isXmlAttribute": false, "isXmlWrapped": false, "additionalPropertiesIsAnyType": false, "hasVars": false, "hasRequired": false, "hasDiscriminatorWithNonEmptyMapping": false, "datatype": "UserType", "iexclusiveMaximum": false } ], "readOnlyVars": [], "readWriteVars": [ { "openApiType": "UserType", "baseName": "type", "complexType": "UserType", "getter": "getType", "setter": "setType", "description": "type of user", "dataType": "UserType", "datatypeWithEnum": "UserType", "name": "type", "defaultValueWithParam": " = data.type;", "baseType": "UserType", "unescapedDescription": "type of user", "example": "null", "jsonSchema": "{\n \"description\" : \"type of user\",\n \"allOf\" : [ {\n \"$ref\" : \"#/components/schemas/UserType\"\n } ]\n}", "exclusiveMinimum": false, "exclusiveMaximum": false, "required": false, "deprecated": false, "hasMoreNonReadOnly": false, "isPrimitiveType": false, "isModel": true, "isContainer": false, "isString": false, "isNumeric": false, "isInteger": false, "isShort": false, "isLong": false, "isUnboundedInteger": false, "isNumber": false, "isFloat": false, "isDouble": false, "isDecimal": false, "isByteArray": false, "isBinary": false, "isFile": false, "isBoolean": false, "isDate": false, "isDateTime": false, "isUuid": false, "isUri": false, "isEmail": false, "isNull": false, "isFreeFormObject": false, "isAnyType": true, "isArray": false, "isMap": false, "isEnum": false, "isReadOnly": false, "isWriteOnly": false, "isNullable": true, "isSelfReference": false, "isCircularReference": false, "isDiscriminator": false, "vars": [], "requiredVars": [], "vendorExtensions": {}, "hasValidation": false, "isInherited": false, "nameInCamelCase": "Type", "nameInSnakeCase": "TYPE", "uniqueItems": false, "isXmlAttribute": false, "isXmlWrapped": false, "additionalPropertiesIsAnyType": false, "hasVars": false, "hasRequired": false, "hasDiscriminatorWithNonEmptyMapping": false, "datatype": "UserType", "iexclusiveMaximum": false } ], "parentVars": [], "mandatory": [], "allMandatory": [], "imports": [ "package:digitalworkkit_visitor_api/src/model/user_type.dart" ], "hasVars": true, "emptyVars": false, "hasMoreModels": false, "hasEnums": false, "isEnum": false, "hasValidation": false, "isNullable": false, "hasRequired": false, "hasOptional": true, "isArray": false, "hasChildren": false, "isMap": true, "isNull": false, "isDeprecated": false, "hasOnlyReadOnly": false, "vendorExtensions": { "x-has-vars": true }, "isAdditionalPropertiesTrue": false, "uniqueItems": false, "exclusiveMinimum": false, "exclusiveMaximum": false, "isModel": false, "hasDiscriminatorWithNonEmptyMapping": false, "isAnyType": false, "isClassnameSanitized": false } }, { "importPath": "lib.src.model.UserType", "model": { "anyOf": [], "oneOf": [], "allOf": [], "anyOfProps": [], "allOfProps": [], "oneOfProps": [], "name": "UserType", "classname": "UserType", "title": "UserType", "classVarName": "userType", "modelJson": "{\n \"title\" : \"UserType\",\n \"type\" : \"string\",\n \"enum\" : [ \"admin\", \"user\" ]\n}", "dataType": "String", "classFilename": "user_type", "isAlias": false, "isString": true, "isInteger": false, "isLong": false, "isNumber": false, "isNumeric": false, "isFloat": false, "isDouble": false, "isDate": false, "isDateTime": false, "isShort": false, "isUnboundedInteger": false, "isBoolean": false, "additionalPropertiesIsAnyType": false, "vars": [], "allVars": [], "requiredVars": [], "optionalVars": [], "readOnlyVars": [], "readWriteVars": [], "parentVars": [], "allowableValues": { "values": [ "admin", "user" ], "enumVars": [ { "name": "admin", "isString": true, "value": "'admin'" }, { "name": "user", "isString": true, "value": "'user'" } ] }, "mandatory": [], "allMandatory": [], "imports": [], "hasVars": false, "emptyVars": false, "hasMoreModels": false, "hasEnums": false, "isEnum": true, "hasValidation": false, "isNullable": false, "hasRequired": false, "hasOptional": false, "isArray": false, "hasChildren": false, "isMap": false, "isNull": false, "isDeprecated": false, "hasOnlyReadOnly": true, "vendorExtensions": { "x-has-vars": false }, "isAdditionalPropertiesTrue": false, "uniqueItems": false, "exclusiveMinimum": false, "exclusiveMaximum": false, "isModel": false, "hasDiscriminatorWithNonEmptyMapping": false, "isAnyType": false, "isClassnameSanitized": false } } ] ```

This causes issues when generating a client with dart-dio-next, as it will generate deserialization logic that doesn’t compile:

      switch (key) {
        case r'type':
          final valueDes = serializers.deserialize(value,
              specifiedType: const FullType.nullable(UserType)) as UserType?;
          if (valueDes == null) continue;
          result.type.replace(valueDes);
          break;
      }

The line that doesn’t compile is result.type.replace(valueDes);, as the UserType EnumClass doesn’t have a replace method.

The replace method is generated there because the generator thinks the UserType field is a model, but it’s actually an enum.

openapi-generator version

5.3.0

OpenAPI declaration file content or url

sample json spec: https://gist.github.com/josh-burton/8062bc64212db27e2a2f879ae65c07dd

Generation Details

dart-dio-next with built value

Steps to reproduce

Generate the client, run pub run build_runner build.

Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/pull/6914

Suggest a fix

I think the true fix for this would be parsing the allOf block correctly. A work around in dart-dio-next would be ok too but I’m not sure how we can work around it when we don’t know the actual type of the model.

@kuhnroyal @wing328

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
josh-burtoncommented, Nov 23, 2021

So to recap this for me, allOf/anyOf with one enum schema ref generates the correct property but wrong serialization code because we don’t know that it is an enum?

yeah that’s right.

1reaction
josh-burtoncommented, Nov 22, 2021

Can you check if this is the same as #9443

Yep, looks like the same issue

Read more comments on GitHub >

github_iconTop Results From Across the Web

JSON schema anyOf validation based on one of properties
1 Answer 1 · Json schema arrays don't have properties , they have items . · Within those properties you're defining name as...
Read more >
Schema generation rules · GitBook - Goswagger.Io
For each schema, go-swagger will generate one or more model types in go. ... anyOf , oneOf and not constructs are not supported...
Read more >
1786273 – [4.6] KAS pod logs show "error building openapi ...
This bug hasn't had any activity in the last 30 days. Maybe the problem got resolved, was a duplicate of something else, or...
Read more >
Support for oneOf, anyOf and allOf - Liferay Help Center
Since Java doesn't support Union Types, use an Object to model the property: EntityA: properties: nameA: type: string EntityB: properties: nameB: anyOf: ...
Read more >
Tiny Validator for v4 JSON Schema
missing . For more info see the API documentation below. Usage 2: Multi-threaded validation. Storing the error and missing schemas does not work...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found