Thanks for the elaborate investigation. Since there’s a ticket opened for the second issue you mentioned, would you mind opening one for the first issue?
From: <[email protected]> on behalf of Michael Günnewig <[email protected]> Reply-To: "[email protected]" <[email protected]> Date: Thursday, October 19, 2017 at 05:39 To: Swagger <[email protected]> Subject: Various Swagger 1.5.16 issues with JAXB, Jersey 1.x/2.x and Swagger-UI 2.x and 3.x Hi all. I stumbled about a couple issues with using Swagger.io together with Jersey 1.x and 2.x. The issues can be seen using he following resource methods and the used model classes: @ApiOperation(value="Return List<Item>", notes="Let Jersey/JAXB do the element wrapping") @GET @Path("list") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public List<Item> getModels() { return Arrays.asList(new Item("1", "foo"), new Item("2", "bar")); } @ApiOperation(value="Return Items, which contains List<Item>", notes="JAXB annotations are used so that the result is semantical equivalent to List<Iterm> been returned") @GET @Path("items") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public Items getItems() { return new Items(Arrays.asList(new Item("1", "foo"), new Item("2", "bar"))); } @XmlRootElement(namespace="io.swagger.bug-test") @XmlAccessorType(XmlAccessType.NONE) public final class Item extends Object { @XmlAttribute(required=true) @XmlSchemaType(name="ID") private String id; @XmlElement(required=true) private String value; ... } @XmlRootElement(name="items") @XmlAccessorType(XmlAccessType.NONE) public final class Items extends Object { @XmlElement(namespace="io.swagger.bug-test") private List<Item> item; ... } If we now request the swagger.yaml file for this REST API, we get this: swagger: "2.0" paths: /list: get: summary: "Return List<Item>" description: "Let Jersey/JAXB do the element wrapping" operationId: "getModels" produces: - "application/json" - "application/xml" parameters: [] responses: 200: description: "successful operation" schema: type: "array" items: $ref: "#/definitions/Item" /items: get: summary: "Return Items, which contains List<Item>" description: "JAXB annotations are used so that the result is semantical equivalent\ \ to List<Iterm> been returned" operationId: "getItems" produces: - "application/json" - "application/xml" parameters: [] responses: 200: description: "successful operation" schema: $ref: "#/definitions/Items" definitions: Item: type: "object" required: - "value" properties: value: type: "string" Items: type: "object" properties: item: type: "array" xml: namespace: "io.swagger.bug-test" items: $ref: "#/definitions/Item" xml: name: "items" Using Swagger-UI 2.2.x or 3.0.x produces equivalent JSON examples matching the actual server output. Using Swagger-UI 2.2.x for the XML example produces incorrect examples: GET /list <?xml version="1.0"?> <Inline Model> <value>string</value> </Inline Model> GET /items <?xml version="1.0"?> <items xmlns="io.swagger.bug-test"> <item> <value>string</value> </item> </items> You can see that the "/list" case is producing totally corrupted XML, which has nearly nothing to do with the real one. While the "/items" case is much better already, is it incorrect with respect to namespaces and lacks the id attribute of <item>. Expected would have been: GET /list <?xml version="1.0" encoding="UTF-8"?> <items> <ns:item xmlns:ns="io.swagger.bug-test" id="string"> <value>string</value> </ns:item> </items> GET /items <?xml version="1.0" encoding="UTF-8"?> <items> <ns:item xmlns:ns="io.swagger.bug-test" id="string"> <value>string</value> </ns:item> </items> The <items> and <value> elements have no namespace defined and so reside in the default empty namespace. Just the <item> element belongs to the specified namespace {io.swagger.bug-test}. As the Swagger-UI 3.x does not honor "xml" within the "items" section, I have moved it into the item definition itself as then 2.x and 3.x will use it. This manual produces YAML produces the correct XML examples if we assume that the default namespace just applies to the XML element that defines it and to none of its children in contrast to normal XML: swagger: "2.0" paths: /list: get: summary: "Return List<Item>" description: "Let Jersey/JAXB do the element wrapping" operationId: "getModels" produces: - "application/json" - "application/xml" parameters: [] responses: 200: description: "successful operation" schema: type: "array" xml: wrapped: "true" name: "items" items: $ref: "#/definitions/Item" /items: get: summary: "Return Items, which contains List<Item>" description: "JAXB annotations are used so that the result is semantical equivalent\ \ to List<Iterm> been returned" operationId: "getItems" produces: - "application/json" - "application/xml" parameters: [] responses: 200: description: "successful operation" schema: $ref: "#/definitions/Items" definitions: Item: type: "object" required: - "value" properties: id: type: "string" xml: attribute: "true" value: type: "string" xml: name: "item" namespace: "io.swagger.bug-test" Items: type: "object" properties: item: type: "array" items: $ref: "#/definitions/Item" xml: name: "items" With the above YAML specification the 2.x and 3.x Swagger UIs produce the following XML examples for both methods, which is much closer to the actual XML received: <?xml version="1.0" encoding="UTF-8"?> <items> <item xmlns="io.swagger.bug-test" id="string"> <value>string</value> </item> </items> As reference the actual Jersey output is: GET /list <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <items> <ns2:item xmlns:ns2="io.swagger.bug-test" id="1"> <value>foo</value> </ns2:item> <ns2:item xmlns:ns2="io.swagger.bug-test" id="2"> <value>bar</value> </ns2:item> </items> GET /items <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <items xmlns:ns2="io.swagger.bug-test"> <ns2:item id="1"> <value>foo</value> </ns2:item> <ns2:item id="2"> <value>bar</value> </ns2:item> </items> As the issue also applies if the Jersey 1.x framework is been used and is independent of the Swagger UI version been used, would I think that the issue resides in the swagger-core and swagger-jaxrs packages. The io.swagger.converter.ModelConverters.readAsProperty(Type) is been invoked for the response types, but has not means to pass this information to the MovelConverter.resolveProperty method, so that the io.swagger.jackson.ModelConverter can not add the "wrapped" flag. Note also that if the name parameter to the @XmlRootElement of the Items class is left out, that the incorrect "Items" name is used instead by Swagger. Also the @XmlAttribute annotations do not seem to be honoured. And if no namespace is defined within any @XmlElement or @XmlRootElement, the one from the @XmlSchema is been used if any, otherwise the empty string is been used. This is not correctly implemented by the Swagger side either, as well as if the namespace is explicitly set to an empty string with the @XmlSchema defined as package level. So in summary: - @XmlAttribute is not used by swagger-core - namespace="" is not applied correctly if @XmlSchema is used at package-level - @ApiOperation which return some collection, like List<Object>, lack "xml: {wrapped:true}" and the correct XML name for the wrapper This seems to be covered already by https://github.com/swager-api/swagger-core/issues/2334 Regards, Michael -- You received this message because you are subscribed to the Google Groups "Swagger" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Swagger" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
