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

refs #371 - better null example handling, new x-inflector-null-example extension processing #375

Merged
merged 2 commits into from
Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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