Skip to content

Commit

Permalink
Merge branch 'bug/2767/example-not-working'
Browse files Browse the repository at this point in the history
fixes #2767
  • Loading branch information
dilipkrish committed Jul 9, 2020
2 parents 94e418f + d513492 commit 311aa95
Show file tree
Hide file tree
Showing 13 changed files with 441 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package springfox.test.contract.oas.bugs;

import io.swagger.annotations.ApiModelProperty;

public class Bug2767 {
public static class ErrorResponse {
@ApiModelProperty(required = true, example = "address")
private String invalidField;

public String getInvalidField() {
return invalidField;
}

public void setInvalidField(String invalidField) {
this.invalidField = invalidField;
}
}

public static class Response {
@ApiModelProperty(required = true, example = "some data")
private String data;

public String getData() {
return data;
}

public void setData(String data) {
this.data = data;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package springfox.test.contract.oas.bugs;

import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ExampleProperty;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -57,4 +63,50 @@ public void bug2982Model(Bug2982.MyClass input) {
@PostMapping("/2982/body")
public void bug2982Body(@RequestBody Bug2982.MyClass input) {
}


@ApiResponses(value = {
@ApiResponse(code = 400, message = "Not Found",
examples = @io.swagger.annotations.Example(
value = {
@ExampleProperty(
mediaType = "application/json",
value = "{'invalidField': 'address'}"),
@ExampleProperty(
mediaType = "text/plain",
value = "The address was invalid")}),
response = Bug2767.ErrorResponse.class)})
@GetMapping("/2767/swagger15")
public Bug2767.Response bug2767() {
return new Bug2767.Response();
}

@io.swagger.v3.oas.annotations.responses.ApiResponses(
value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "400",
description = "Bad Input",
content = {
@Content(mediaType = "application/json",
examples = {
@ExampleObject(name = "foo",
summary = "foo example",
value = "{'invalidField': 'foo'}",
description = "Foo response"
),
@ExampleObject(name = "bar",
summary = "bar example",
value = "{'invalidField': 'bar'}",
description = "Bar response"
)
},
schema = @Schema(implementation = Bug2767.ErrorResponse.class))
}
)
}
)
@GetMapping("/2767/swagger20")
public Bug2767.Response bug2767New() {
return new Bug2767.Response();
}
}
109 changes: 109 additions & 0 deletions oas-contract-tests/src/test/resources/contracts/bugs.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,89 @@
}
],
"paths": {
"/bugs/2767/swagger15": {
"get": {
"tags": [
"bugs-controller"
],
"summary": "bug2767",
"operationId": "bug2767UsingGET",
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Response"
}
}
}
},
"400": {
"description": "Not Found",
"content": {
"application/json": {
"examples": {
"example-0": {
"value": "{'invalidField': 'address'}"
}
}
},
"text/plain": {
"examples": {
"example-1": {
"value": "The address was invalid"
}
}
}
}
}
}
}
},
"/bugs/2767/swagger20": {
"get": {
"tags": [
"bugs-controller"
],
"summary": "bug2767New",
"operationId": "bug2767NewUsingGET",
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Response"
}
}
}
},
"400": {
"description": "Bad Input",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
},
"examples": {
"bar": {
"summary": "bar example",
"description": "Bar response",
"value": "{'invalidField': 'bar'}"
},
"foo": {
"summary": "foo example",
"description": "Foo response",
"value": "{'invalidField': 'foo'}"
}
}
}
}
}
}
}
},
"/bugs/2982/body": {
"post": {
"tags": [
Expand Down Expand Up @@ -282,6 +365,19 @@
}
}
},
"ErrorResponse": {
"title": "ErrorResponse",
"required": [
"invalidField"
],
"type": "object",
"properties": {
"invalidField": {
"type": "string",
"example": "address"
}
}
},
"MyClass": {
"title": "MyClass",
"type": "object",
Expand Down Expand Up @@ -334,6 +430,19 @@
}
}
},
"Response": {
"title": "Response",
"required": [
"data"
],
"type": "object",
"properties": {
"data": {
"type": "string",
"example": "some data"
}
}
},
"Tag": {
"title": "Tag",
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,6 @@ public Example build() {
description,
value,
externalValue,
mediaType);
emptyToNull(mediaType));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
Expand Down Expand Up @@ -83,6 +84,7 @@ public void setupModule(SetupContext context) {
context.setMixInAnnotations(XML.class, NonEmptyMixin.class);
context.setMixInAnnotations(Tag.class, NonEmptyMixin.class);
context.setMixInAnnotations(Contact.class, NonEmptyMixin.class);
context.setMixInAnnotations(Example.class, NonEmptyMixin.class);

}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
package springfox.documentation.oas.mappers;

import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import springfox.documentation.schema.Example;

import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;

import static springfox.documentation.builders.BuilderDefaults.*;

@Mapper(componentModel = "spring", uses = VendorExtensionsMapper.class)
public interface ExamplesMapper {
default Map<String, io.swagger.v3.oas.models.examples.Example> mapExamples(Collection<Example> from) {
Map<String, io.swagger.v3.oas.models.examples.Example> examples = new TreeMap<>();
for (Example each : from) {
examples.put(
each.getMediaType().orElse(""),
each.getId(),
toOasExample(each));
}
return examples;
}

@AfterMapping
default void afterMappingParameter(
Example from,
@MappingTarget io.swagger.v3.oas.models.examples.Example target) {
target.extensions(new VendorExtensionsMapper().mapExtensions(from.getExtensions()));
}

@Mappings({
@Mapping(target = "$ref", ignore = true)
@Mapping(target = "$ref", ignore = true),
@Mapping(target = "extensions", ignore = true)
})
io.swagger.v3.oas.models.examples.Example toOasExample(Example from);
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@
import org.mapstruct.factory.Mappers;
import org.slf4j.Logger;
import org.springframework.http.HttpMethod;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import springfox.documentation.schema.CollectionElementFacet;
import springfox.documentation.schema.ElementFacet;
import springfox.documentation.schema.EnumerationFacet;
import springfox.documentation.schema.Example;
import springfox.documentation.schema.NumericElementFacet;
import springfox.documentation.schema.StringElementFacet;
import springfox.documentation.service.ApiDescription;
Expand All @@ -64,11 +67,14 @@
import springfox.documentation.service.SimpleParameterSpecification;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.slf4j.LoggerFactory.*;
Expand Down Expand Up @@ -192,10 +198,31 @@ protected ApiResponses map(
ApiResponse response = new ApiResponse()
.description(each.getDescription());
Content content = new Content();
for (Representation representation : each.getRepresentations()) {
ExamplesMapper exampleMapper = Mappers.getMapper(ExamplesMapper.class);
MultiValueMap<String, Example> examplesByMediaType
= new LinkedMultiValueMap<>();
for (Example example : each.getExamples()) {
examplesByMediaType.add(example.getMediaType().orElse("*/*"), example);
}
Map<String, Representation> representations
= each.getRepresentations().stream()
.collect(Collectors.toMap(
e -> e.getMediaType().toString(),
Function.identity(),
(o1, o2) -> o1, TreeMap::new));
Set<String> mediaTypes = new HashSet<>(representations.keySet());
mediaTypes.addAll(examplesByMediaType.keySet());
for (String eachMediaType : mediaTypes) {
MediaType mediaType = fromRepresentation(
representations.getOrDefault(eachMediaType, null),
modelNamesRegistry);
if (mediaType == null) {
mediaType = new MediaType();
}
mediaType.examples(exampleMapper.mapExamples(nullToEmptyList(examplesByMediaType.get(eachMediaType))));
content.addMediaType(
representation.getMediaType().toString(),
fromRepresentation(representation, modelNamesRegistry));
eachMediaType,
mediaType);
}
response.setContent(content);
response.setHeaders(fromHeaders(each.getHeaders(), modelNamesRegistry));
Expand Down Expand Up @@ -276,7 +303,7 @@ private Content map(
@Mappings({
@Mapping(target = "schema", source = "model", qualifiedByName = "ModelsMapping"),
@Mapping(target = "encoding", source = "encodings"),
@Mapping(target = "examples", source = "model.facetExamples"),
@Mapping(target = "examples", ignore = true),
@Mapping(target = "example", ignore = true),
@Mapping(target = "extensions", source = "model.facetExtensions")
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ protected Set<Response> read(OperationContext context) {
if (!isEmpty(eachExample.value())) {
examples.add(new ExampleBuilder()
.mediaType(each.mediaType())
.description(eachExample.description())
.summary(eachExample.summary())
.id(eachExample.name())
.value(eachExample.value()).build());
}
}
Expand Down

0 comments on commit 311aa95

Please sign in to comment.