Skip to content

Swagger Parser does not evaluate references for nested map properties. #975

@douglasbgray

Description

@douglasbgray

Found in 2.0.8-SNAPSHOT of Swagger parser.

When there is a map property with a map property, and the final type is a reference in another file, then the reference processor does not normalize the reference path relative to the file location of the root contract. This causes a file not found error when running the code generator.

Caused by: java.lang.RuntimeException: Could not find ./types.yaml on the classpath
    at io.swagger.v3.parser.util.ClasspathHelper.loadFileFromClasspath (ClasspathHelper.java:31)
    at io.swagger.v3.parser.util.RefUtils.readExternalRef (RefUtils.java:177)
    at io.swagger.v3.parser.ResolverCache.loadRef (ResolverCache.java:118)
    at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalSchema (ExternalRefProcessor.java:51)
    at io.swagger.v3.parser.processors.SchemaProcessor.processReferenceSchema (SchemaProcessor.java:202)
    at io.swagger.v3.parser.processors.SchemaProcessor.processAdditionalProperties (SchemaProcessor.java:74)
    at io.swagger.v3.parser.processors.SchemaProcessor.processSchemaType (SchemaProcessor.java:61)
    at io.swagger.v3.parser.processors.SchemaProcessor.processArraySchema (SchemaProcessor.java:188)
    at io.swagger.v3.parser.processors.SchemaProcessor.processSchemaType (SchemaProcessor.java:47)
    at io.swagger.v3.parser.processors.SchemaProcessor.processPropertySchema (SchemaProcessor.java:105)
    at io.swagger.v3.parser.processors.SchemaProcessor.processSchemaType (SchemaProcessor.java:54)
    at io.swagger.v3.parser.processors.SchemaProcessor.processSchema (SchemaProcessor.java:39)
    at io.swagger.v3.parser.processors.ComponentsProcessor.processSchemas (ComponentsProcessor.java:222)
    at io.swagger.v3.parser.processors.ComponentsProcessor.processComponents (ComponentsProcessor.java:72)
    at io.swagger.v3.parser.OpenAPIResolver.resolve (OpenAPIResolver.java:50)
    at io.swagger.v3.parser.OpenAPIV3Parser.readLocation (OpenAPIV3Parser.java:53)
    at io.swagger.parser.OpenAPIParser.readLocation (OpenAPIParser.java:19)

Sample test case for reproducing is here - https://github.com/douglasbgray/ref_processor_example

In researching, the problem lies in an incomplete implementation of the method processProperties in the ExternalRefProcessor. The method does not recurse in all situations, so depending on the contract, it can lead to an incomplete reference resolution.

I was able to fix the issue by replacing that method with these 3 methods:

    private void processProperty(Schema subProp, String file) {
        if (subProp != null) {
            if (StringUtils.isNotBlank(subProp.get$ref())) {
                processRefSchema(subProp, file);
            }
            if (subProp.getProperties() != null) {
                processProperties(subProp.getProperties(), file);
            }
            if (subProp instanceof ArraySchema) {
                processProperty(((ArraySchema) subProp).getItems(), file);
            }
            if (subProp.getAdditionalProperties() instanceof Schema) {
                processProperty(((Schema) subProp.getAdditionalProperties()), file);
            }
            if (subProp instanceof ComposedSchema) {
                ComposedSchema composed = (ComposedSchema) subProp;
                processProperties(composed.getAllOf(), file);
                processProperties(composed.getAnyOf(), file);
                processProperties(composed.getOneOf(), file);
            }
        }
    }

    private void processProperties(Collection<Schema> subProps, String file) {
        if (subProps != null) {
            for (Schema subProp : subProps) {
                processProperty(subProp, file);
            }
        }
    }

    private void processProperties(Map<String, Schema> subProps, String file) {
        if (subProps != null) {
            processProperties(subProps.values(), file);
        }
    }

If a PR would be welcomed, I can put one together with the change and some unit tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions