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.

OpenAPIV3Parser setting null instead of parsing default enum values

See original GitHub issue

Hi,

I’ve discovered what seems to be an issue when OpenAPIV3Parser parses specifications containing default values for enum types.

When io.swagger.v3.parser.OpenAPIV3Parser#read(java.lang.String) parses default values for enums, the returned OpenAPI model schemas contain null instead of default values. This applies for both defaults set in enums themselves or inside schemas referencing the enums. The same specification that exposes this issue is valid and properly shows defaults inside Swagger Editor. This seems to be in line with Schema Object in the OpenAPI specification.

I’m providing a test class with unit tests that confirm my claims alongside an example OpenAPI specification that is used in tests and can be run inside Swagger Editor. The tests should be easy to add to your existing OpenAPIV3ParserTest. This is tested using swagger-parser versions 2.0.14 and 2.0.22.

Can you please look into this and see if my findings are correct?

Test class

The class contains various examples of setting default values for enums that do or do not set the default values themselves. Assertions are based on behavior in Swagger Editor. Ignored tests are the ones exposing the issue.

package io.swagger.v3.parser.test;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.parser.OpenAPIV3Parser;
import org.junit.*;

import java.io.File;

import static org.assertj.core.api.BDDAssertions.then;

public class OpenAPIV3ParserTest {

    private static final String GIVEN_SPEC_PATH = "src/test/resources/openapis/openapi-default-enum-bug.json";
    private static final String GIVEN_LOCATION = new File(GIVEN_SPEC_PATH).getAbsolutePath();

    private OpenAPIV3Parser openAPIV3Parser;

    @Before
    public void setUp() {
        openAPIV3Parser = new OpenAPIV3Parser();
    }

    @Test
    public void shouldParseDefaultForEnumSchema() {
        // when
        OpenAPI openAPI = openAPIV3Parser.read(GIVEN_LOCATION);

        // then
        then(openAPI.getComponents()
                .getSchemas()
                .get("Enum")
                .getDefault()
        ).isNull();
    }

    @Test
    public void shouldParseDefaultForEnumWithDefaultSchema() {
        // when
        OpenAPI openAPI = openAPIV3Parser.read(GIVEN_LOCATION);

        // then
        then(openAPI.getComponents()
                .getSchemas()
                .get("EnumWithDefault")
                .getDefault()
        ).isEqualTo("ENUM_DEFAULT");
    }

    @Test
    public void shouldParseDefaultForSchemaWithEnum() {
        // when
        OpenAPI openAPI = openAPIV3Parser.read(GIVEN_LOCATION);

        // then
        then(openAPI.getComponents()
                .getSchemas()
                .get("SchemaWithEnum")
                .getDefault()
        ).isNull();
    }

    @Ignore("This test fails due to OpenAPIV3Parser bug.")
    @Test
    public void shouldParseDefaultForSchemaWithDefaultAndEnum() {
        // when
        OpenAPI openAPI = openAPIV3Parser.read(GIVEN_LOCATION);

        // then
        then(openAPI.getComponents()
                .getSchemas()
                .get("SchemaWithDefaultAndEnum")
                .getDefault()
        ).isEqualTo("SCHEMA_DEFAULT");
    }

    @Ignore("This test fails due to OpenAPIV3Parser bug.")
    @Test
    public void shouldParseDefaultForSchemaWithEnumWithDefault() {
        // when
        OpenAPI openAPI = openAPIV3Parser.read(GIVEN_LOCATION);

        // then
        then(openAPI.getComponents()
                .getSchemas()
                .get("SchemaWithEnumWithDefault")
                .getDefault()
        ).isEqualTo("ENUM_DEFAULT");
    }

    @Ignore("This test fails due to OpenAPIV3Parser bug.")
    @Test
    public void shouldParseDefaultForSchemaWithDefaultAndEnumWithDefault() {
        // when
        OpenAPI openAPI = openAPIV3Parser.read(GIVEN_LOCATION);

        // then
        then(openAPI.getComponents()
                .getSchemas()
                .get("SchemaWithDefaultAndEnumWithDefault")
                .getDefault()
        ).isEqualTo("SCHEMA_DEFAULT");
    }

}

Example specification

This specification is used in the test above and is named openapi-default-enum-bug.json for testing purposes.

{
  "openapi": "3.0.1",
  "info": {
    "title": "Here be enum bugs",
    "description": "OpenAPI spec to test the enum parsing bugs.",
    "version": "1.0.0"
  },
  "paths": {
    "/enum/parse/bug": {
      "post": {
        "summary": "Test enum parse bug",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestRequest"
              }
            }
          }
        },
        "responses": {
          "default": {
            "description": "Successful response"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "TestRequest": {
        "type": "object",
        "description": "This request body schema depicts various enum and default value combinations inside schemas of the following properties.",
        "properties": {
          "schemaWithEnum": {
            "$ref": "#/components/schemas/SchemaWithEnum"
          },
          "schemaWithDefaultAndEnum": {
            "$ref": "#/components/schemas/SchemaWithDefaultAndEnum"
          },
          "schemaWithEnumWithDefault": {
            "$ref": "#/components/schemas/SchemaWithEnumWithDefault"
          },
          "schemaWithDefaultAndEnumWithDefault": {
            "$ref": "#/components/schemas/SchemaWithDefaultAndEnumWithDefault"
          }
        }
      },
      "SchemaWithEnum": {
        "type": "object",
        "properties": {
          "enumProperty": {
            "description": "This schema with no default values set behaves properly in Swagger Editor and when parsed with OpenAPIV3Parser.",
            "allOf": [
              {
                "$ref": "#/components/schemas/Enum"
              }
            ]
          }
        }
      },
      "SchemaWithDefaultAndEnum": {
        "type": "object",
        "properties": {
          "enumProperty": {
            "description": "This schema with set default enum value and enum ref shows default \"SCHEMA_DEFAULT\" value in Swagger Editor, but is null when parsed with OpenAPIV3Parser.",
            "allOf": [
              {
                "$ref": "#/components/schemas/Enum"
              }
            ],
            "default": "SCHEMA_DEFAULT"
          }
        }
      },
      "SchemaWithEnumWithDefault": {
        "type": "object",
        "properties": {
          "enumProperty": {
            "description": "This schema with ref to enum with set default value shows default \"ENUM_DEFAULT\" value in Swagger Editor, but is null when parsed with OpenAPIV3Parser.",
            "allOf": [
              {
                "$ref": "#/components/schemas/EnumWithDefault"
              }
            ]
          }
        }
      },
      "SchemaWithDefaultAndEnumWithDefault": {
        "type": "object",
        "properties": {
          "enumProperty": {
            "description": "This schema with set default enum value and ref to enum with set default value shows default \"SCHEMA_DEFAULT\" value in Swagger Editor, but is null when parsed with OpenAPIV3Parser.",
            "allOf": [
              {
                "$ref": "#/components/schemas/EnumWithDefault"
              }
            ],
            "default": "SCHEMA_DEFAULT"
          }
        }
      },
      "Enum": {
        "type": "string",
        "enum": [
          "SCHEMA_DEFAULT",
          "NOT_DEFAULT"
        ]
      },
      "EnumWithDefault": {
        "type": "string",
        "enum": [
          "SCHEMA_DEFAULT",
          "ENUM_DEFAULT",
          "NOT_DEFAULT"
        ],
        "default": "ENUM_DEFAULT"
      }
    }
  }
}

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
bfreudencommented, Sep 13, 2022

@tmeckel my first comment was the result of the inspection of the source code of 2.0.x. Sorry. Version 2.1.2 is working much better in this regard, and I think the little fix in ResolverFully is just the icing on the cake.

1reaction
bfreudencommented, Sep 14, 2022

I’ve just added all the tests and made an adjustement to ResolverFully so it sets a default value when all combined models have the same default value. It is almost completely fixed now. I’m saying “almost” because I’m not sure the SchemaWithEnumWithDefault case is supposed to be working when resolve=false and aggregateCombinators=false. I don’t think so (and it isn’t working). In my opinion that’s the purpose of the resolve=true and aggregateCombinators=true, and it’s working with those parameters as shown by new unit tests.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Enum default value is set to null · Issue #3608 - GitHub
The C# generated code sets the default value of this enum property to null in the class' constructor. This results in a compilation...
Read more >
c# - How can I ignore unknown enum values during json ...
I would be happy with either marking special value as Unknown or using a nullable enum and unmatched value would return null. c#...
Read more >
Assigning a default value if one doesnt exist in enum - Support
I wanted to know if it was possible to set a default value for a enum class if a value doesn't exist in...
Read more >
Enum.ToString Method (System) - Microsoft Learn
Converts the value of this instance to its equivalent string representation.
Read more >
How To Serialize and Deserialize Enums with Jackson
Default Enum Representation. By default, Jackson will represent Java Enums as a simple String. For instance: new ObjectMapper().
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