Skip to content

Commit

Permalink
Merge pull request #375 from swagger-api/issue-371
Browse files Browse the repository at this point in the history
refs #371 - better null example handling, new `x-inflector-null-example` extension processing
  • Loading branch information
frantuma authored Jul 16, 2020
2 parents 61aa406 + 9863e2d commit f61427c
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/main/java/io/swagger/oas/inflector/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class Constants {
public static final String X_SWAGGER_ROUTER_CONTROLLER = VendorExtension.X_SWAGGER_ROUTER_CONTROLLER.getValue();
public static final String X_SWAGGER_ROUTER_MODEL = VendorExtension.X_SWAGGER_ROUTER_MODEL.getValue();
public static final String X_INFLECTOR_HIDDEN = "x-inflector-hidden";
public static final String X_INFLECTOR_NULL_EXAMPLE = "x-inflector-null-example";

public enum VendorExtension {
X_SWAGGER_ROUTER_CONTROLLER("x-swagger-router-controller"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.swagger.oas.inflector.examples;

import io.swagger.oas.inflector.Constants;
import io.swagger.oas.inflector.examples.models.ArrayExample;
import io.swagger.oas.inflector.examples.models.BooleanExample;
import io.swagger.oas.inflector.examples.models.DecimalExample;
Expand All @@ -24,6 +25,7 @@
import io.swagger.oas.inflector.examples.models.FloatExample;
import io.swagger.oas.inflector.examples.models.IntegerExample;
import io.swagger.oas.inflector.examples.models.LongExample;
import io.swagger.oas.inflector.examples.models.NullExample;
import io.swagger.oas.inflector.examples.models.ObjectExample;
import io.swagger.oas.inflector.examples.models.StringExample;

Expand Down Expand Up @@ -84,10 +86,19 @@ public static Example fromSchema(Schema property, Map<String, Schema> definition
return fromProperty(null, property, definitions, new HashMap<>(), null);
}

public static Example fromSchema(Schema property, Map<String, Schema> definitions, boolean nullExample, boolean processNullExampleExtension) {
return fromProperty(null, property, definitions, new HashMap<>(), null, nullExample, processNullExampleExtension);
}

public static Example fromSchema(Schema property, Map<String, Schema> definitions, RequestType requestType) {
return fromProperty(null,property, definitions, new HashMap<>(), requestType);
}

public static Example fromSchema(Schema property, Map<String, Schema> definitions, RequestType requestType, boolean nullExample, boolean processNullExampleExtension) {
return fromProperty(null,property, definitions, new HashMap<>(), requestType, nullExample, processNullExampleExtension);
}


public static Example fromProperty(String name, Schema property, Map<String, Schema> definitions, Set<String> processedModels, RequestType requestType) {
Map<String, Example> map = new HashMap<>();
for (String key : processedModels) {
Expand All @@ -97,6 +108,18 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch
}

public static Example fromProperty(String name, Schema property, Map<String, Schema> definitions, Map<String, Example> processedModels, RequestType requestType) {
return fromProperty(name, property, definitions, processedModels, requestType, false, false);
}

public static Example fromProperty(
String name,
Schema property,
Map<String, Schema> definitions,
Map<String, Example> processedModels,
RequestType requestType,
boolean nullExample,
boolean processNullExampleExtension) {

if (property == null) {
return null;
}
Expand Down Expand Up @@ -126,6 +149,17 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch

Object example = property.getExample();

if (example == null) {
if (nullExample) {
return new NullExample();
}
if (processNullExampleExtension) {
if (property.getExtensions() != null && property.getExtensions().get(Constants.X_INFLECTOR_NULL_EXAMPLE) != null) {
return new NullExample();
}
}
}

if (property.get$ref() != null) {
String ref = property.get$ref();
ref = ref.substring(ref.lastIndexOf("/") + 1);
Expand All @@ -137,7 +171,7 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch
if( definitions != null ) {
Schema model = definitions.get(ref);
if (model != null) {
output = fromProperty(ref, model, definitions, processedModels, requestType);
output = fromProperty(ref, model, definitions, processedModels, requestType, nullExample, processNullExampleExtension);
processedModels.put(ref, output);
return output;
}
Expand Down Expand Up @@ -331,7 +365,7 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch
if(op.getProperties() != null) {
for(String propertyname : op.getProperties().keySet()) {
Schema inner = op.getProperties().get(propertyname);
Example innerExample = fromProperty(null, inner, definitions,processedModels, requestType);
Example innerExample = fromProperty(null, inner, definitions,processedModels, requestType, nullExample, processNullExampleExtension);
outputExample.put(propertyname, innerExample);
}
output = outputExample;
Expand All @@ -351,7 +385,7 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch
ArraySchema ap = (ArraySchema) property;
Schema inner = ap.getItems();
if (inner != null) {
Object innerExample = fromProperty(null,inner, definitions, processedModels,requestType);
Object innerExample = fromProperty(null,inner, definitions, processedModels,requestType, nullExample, processNullExampleExtension);
if (innerExample != null) {
if (innerExample instanceof Example) {
ArrayExample an = new ArrayExample();
Expand All @@ -373,7 +407,7 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch
List<Example> innerExamples = new ArrayList<>();
if (models != null) {
for (Schema im : models) {
Example innerExample = fromProperty(null, im, definitions, processedModels, requestType);
Example innerExample = fromProperty(null, im, definitions, processedModels, requestType, nullExample, processNullExampleExtension);
if (innerExample != null) {
innerExamples.add(innerExample);
}
Expand All @@ -386,7 +420,7 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch
List<Schema> models = composedSchema.getAnyOf();
if (models != null) {
for (Schema im : models) {
Example innerExample = fromProperty(null, im, definitions, processedModels, requestType);
Example innerExample = fromProperty(null, im, definitions, processedModels, requestType, nullExample, processNullExampleExtension);
if (innerExample != null) {
output = innerExample;
break;
Expand All @@ -399,7 +433,7 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch

if (models != null) {
for (Schema im : models) {
Example innerExample = fromProperty(null, im, definitions, processedModels, requestType);
Example innerExample = fromProperty(null, im, definitions, processedModels, requestType, nullExample, processNullExampleExtension);
if (innerExample != null) {
output = innerExample;
break;
Expand All @@ -423,7 +457,7 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch
Map<String,Schema> properties = property.getProperties();
for(String propertyKey : properties.keySet()) {
Schema inner = properties.get(propertyKey);
Example propExample = fromProperty(null, inner, definitions, processedModels,requestType);
Example propExample = fromProperty(null, inner, definitions, processedModels,requestType, nullExample, processNullExampleExtension);
ex.put(propertyKey, propExample);
}
}
Expand All @@ -436,7 +470,7 @@ public static Example fromProperty(String name, Schema property, Map<String, Sch
Schema inner = (Schema) property.getAdditionalProperties();
if (inner != null) {
for (int i = 1; i <= 3; i++) {
Example innerExample = fromProperty(null, inner, definitions, processedModels, requestType);
Example innerExample = fromProperty(null, inner, definitions, processedModels, requestType, nullExample, processNullExampleExtension);
if (innerExample != null) {
if (output == null) {
output = new ObjectExample();
Expand Down Expand Up @@ -516,4 +550,4 @@ public static void mergeTo(ObjectExample output, List<Example> examples) {
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2017 SmartBear Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.swagger.oas.inflector.examples.models;


public class NullExample extends AbstractExample {

public NullExample() {
super.setTypeName("string");
}

public String asString() {
return null;
}

public Object getValue() {
return null;
}

public void setValue(Object value) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.fasterxml.jackson.databind.node.FloatNode;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.LongNode;
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ShortNode;
import io.swagger.oas.inflector.examples.models.ArrayExample;
Expand All @@ -40,6 +41,7 @@
import io.swagger.oas.inflector.examples.models.FloatExample;
import io.swagger.oas.inflector.examples.models.IntegerExample;
import io.swagger.oas.inflector.examples.models.LongExample;
import io.swagger.oas.inflector.examples.models.NullExample;
import io.swagger.oas.inflector.examples.models.ObjectExample;
import io.swagger.oas.inflector.examples.models.StringExample;

Expand Down Expand Up @@ -88,6 +90,8 @@ private Example createExample(JsonNode node) {
return new LongExample(node.longValue());
} else if (node instanceof BooleanNode) {
return new BooleanExample(node.booleanValue());
} else if (node instanceof NullNode) {
return new NullExample();
} else {
return new StringExample(node.asText());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.swagger.oas.inflector.examples.models.FloatExample;
import io.swagger.oas.inflector.examples.models.IntegerExample;
import io.swagger.oas.inflector.examples.models.LongExample;
import io.swagger.oas.inflector.examples.models.NullExample;
import io.swagger.oas.inflector.examples.models.ObjectExample;
import io.swagger.oas.inflector.examples.models.StringExample;

Expand Down Expand Up @@ -88,7 +89,7 @@ public void writeValue(JsonGenerator jgen, String field, Example o) throws IOExc
ArrayExample obj = (ArrayExample) o;
jgen.writeArrayFieldStart(field);
for (Example item : obj.getItems()) {
if (item instanceof ObjectExample) {
if (item instanceof ObjectExample) {
jgen.writeStartObject();
writeTo(jgen, item);
jgen.writeEndObject();
Expand Down Expand Up @@ -159,11 +160,17 @@ public void writeValue(JsonGenerator jgen, String field, Example o) throws IOExc
} else {
jgen.writeString(obj.getValue());
}
} else if (o instanceof NullExample) {
if (field != null) {
jgen.writeNullField(field);
} else {
jgen.writeNull();
}
}
}

@Override
public Class<Example> handledType() {
return Example.class;
}
}
}
61 changes: 59 additions & 2 deletions src/test/java/io/swagger/oas/test/examples/ExampleBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package io.swagger.oas.test.examples;

import com.fasterxml.jackson.databind.module.SimpleModule;
import io.swagger.models.Swagger;
import io.swagger.oas.inflector.examples.ExampleBuilder;
import io.swagger.oas.inflector.examples.XmlExampleSerializer;
import io.swagger.oas.inflector.examples.models.AbstractExample;
Expand Down Expand Up @@ -55,6 +54,7 @@
import java.util.Map;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;

public class ExampleBuilderTest {
Expand Down Expand Up @@ -899,7 +899,7 @@ public void testIssue300() throws Exception {
Example example = ExampleBuilder.fromSchema(schema, openAPI.getComponents().getSchemas());
String jsonExample = Json.pretty(example);
assertEqualsIgnoreLineEnding(jsonExample, "{\n \"name\" : \"doggie\",\n \"shots\" : [ \"rabies\" ]\n}");

String xmlExample = new XmlExampleSerializer().serialize(example);
assertEquals(xmlExample, "<?xml version='1.1' encoding='UTF-8'?><Pet><name>doggie</name><shots><shot>rabies</shot></shots></Pet>");
}
Expand Down Expand Up @@ -944,4 +944,61 @@ public void testSwos126() throws Exception {
assertTrue(jsonExample.contains("\"date\" : \"2019-08-05\""));
assertTrue(jsonExample.contains("\"dateTime\" : \"2019-08-05T12:34:56Z\""));
}

@Test
public void testNullExampleSupportOAS3() throws Exception{

ParseOptions options = new ParseOptions();
options.setResolve(true);
options.setResolveFully(true);

OpenAPI openAPI = new OpenAPIV3Parser().read("src/test/swagger/null-examples-oas3.yaml", null, options);

ApiResponse response;
Example example;
String output;

response = openAPI.getPaths().get("/object-with-null-example").getGet().getResponses().get("200");
// returns instance of NullExample
example = ExampleBuilder.fromSchema(response.getContent().get("application/json").getSchema(), null, ExampleBuilder.RequestType.READ, false, true);
assertNull(example.asString());

response = openAPI.getPaths().get("/object-with-null-in-schema-example").getGet().getResponses().get("200");
example = ExampleBuilder.fromSchema(response.getContent().get("application/json").getSchema(), null, ExampleBuilder.RequestType.READ, false, true);
output = Json.pretty(example);
assertEquals(output, "{\n" +
" \"a\" : 5,\n" +
" \"b\" : \"test\",\n" +
" \"c\" : true,\n" +
" \"d\" : " + null + "\n" +
"}");

response = openAPI.getPaths().get("/object-with-null-property-example").getGet().getResponses().get("200");
example = ExampleBuilder.fromSchema(response.getContent().get("application/json").getSchema(), null, ExampleBuilder.RequestType.READ, false, true);
output = Json.pretty(example);
assertEquals(output, "{\n" +
" \"a\" : 5,\n" +
" \"b\" : " + null + "\n" +
"}");

response = openAPI.getPaths().get("/string-with-null-example").getGet().getResponses().get("200");
// returns instance of NullExample
example = ExampleBuilder.fromSchema(response.getContent().get("application/json").getSchema(), null, ExampleBuilder.RequestType.READ, false, true);
assertNull(example.asString());

response = openAPI.getPaths().get("/array-with-null-array-example").getGet().getResponses().get("200");
// returns instance of NullExample
example = ExampleBuilder.fromSchema(response.getContent().get("application/json").getSchema(), null, ExampleBuilder.RequestType.READ, false, true);
assertNull(example.asString());

response = openAPI.getPaths().get("/array-with-null-item-example").getGet().getResponses().get("200");
example = ExampleBuilder.fromSchema(response.getContent().get("application/json").getSchema(), null, ExampleBuilder.RequestType.READ, false, true);
output = Json.pretty(example);
assertEquals(output, "[ " + null + " ]");

response = openAPI.getPaths().get("/array-with-null-in-array-example").getGet().getResponses().get("200");
example = ExampleBuilder.fromSchema(response.getContent().get("application/json").getSchema(), null, ExampleBuilder.RequestType.READ, false, true);
output = Json.pretty(example);
assertEquals(output, "[ \"foo\", " + null + " ]");
}
}
Loading

0 comments on commit f61427c

Please sign in to comment.