Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Where there are multiple fields with same generic definition Map<K, V> (e.g Map<String, String>) then only the first field is rendered in the example text #2972

Closed
camlane opened this issue Oct 2, 2018 · 4 comments

Comments

@camlane
Copy link

camlane commented Oct 2, 2018

Where there are multiple fields with same generic definition Map<K, V> (e.g Map<String, String>) then only the first field is rendered in the example text

When I have a response class with more than one field of type Map<String, String> only the first field will render
in the 'Example Value' part of the response definition in swagger ui

private Map<String, String> myField1;
private Map<String, String> myField2;

Only the below is output

"myField": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  }

However I can see the below lines being output to the log twice.

io.swagger.v3.core.converter.ModelConverterContextImpl resolve: resolve [map type; class java.util.Map, [simple type, class java.lang.String] -> [simple type, class java.lang.String]]

@wcicola
Copy link

wcicola commented Oct 25, 2018

I have been dealing with this issue for the better part of a week and finally managed to nail down the root. The issue begins at line 613 of ModelResolver:

property = context.resolve(aType);

ModelConverterContextImpl (line 77) returns a cached Schema instance if it has already been processed:

if (processedTypes.contains(type)) {
            return modelByType.get(type);
}

ModelResolver at line 666 changes the name of that instance and adds it to the list of properties:

property.setName(propName);
...
props.add(property);

If you use a debugger and inspect props after this line, you can see that it actually contains multiple Schema instances--each with the name of the most recently parsed field. Then at line 674, each instance gets added to modelProps :

for (Schema prop : props) {
            modelProps.put(prop.getName(), prop);
        }

And of course, since they have all been assigned the same name, this results in only the final one being retained in the map.

I changed ModelConverterContextImpl to return a clone of the cached instance, and it now includes all fields:

{
  "type" : "object",
  "properties" : {
    "stringsMap1" : {
      "type" : "object",
      "additionalProperties" : {
        "@class" : "io.swagger.v3.oas.models.media.StringSchema",
        "type" : "string"
      }
    },
    "stringsMap2" : {
      "type" : "object",
      "additionalProperties" : {
        "@class" : "io.swagger.v3.oas.models.media.StringSchema",
        "type" : "string"
      }
    }
  }
}

I will refine this code to only do the cloning when the AnnotatedType is of a Map and do some more testing, and can then create a PR if no other issues arise.

@camlane
Copy link
Author

camlane commented Nov 2, 2018

Hi,
Looks like you've nailed it. Thanks for the investigation and the dev effort!

frantuma added a commit that referenced this issue Nov 2, 2018
ref #2972 - fixes resolving multiple map properties
@frantuma
Copy link
Member

frantuma commented Nov 2, 2018

Thanks a lot to @wcicola for spotting and working on this!

#3001 fixes this and replaces #2997.

Closing ticket, please reopen if still experiencing issues

@frantuma frantuma closed this as completed Nov 2, 2018
@wcicola
Copy link

wcicola commented Nov 2, 2018

My pleasure; thanks to the entire community for building something so useful! It's a privilege to be able to give something back!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants