-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated return types to JsonNode in ExampleJsonGenerator.java
- Loading branch information
dipeshsingh253
committed
Oct 9, 2023
1 parent
6e0c6bf
commit 1de7f6f
Showing
1 changed file
with
53 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import com.fasterxml.jackson.databind.node.*; | ||
import com.fasterxml.jackson.databind.util.RawValue; | ||
import io.swagger.v3.core.util.Json; | ||
import io.swagger.v3.oas.models.media.Schema; | ||
|
@@ -14,12 +14,7 @@ | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.Arrays; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
import java.util.*; | ||
|
||
import static io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigConstants.SPRINGWOLF_SCHEMA_EXAMPLE_GENERATOR; | ||
|
||
|
@@ -29,25 +24,25 @@ | |
public class ExampleJsonGenerator implements ExampleGenerator { | ||
|
||
private static final ObjectMapper objectMapper = Json.mapper(); | ||
private static final String DEFAULT_NUMBER_EXAMPLE = "1.1"; | ||
private static final String DEFAULT_INTEGER_EXAMPLE = "0"; | ||
private static final Double DEFAULT_NUMBER_EXAMPLE = 1.1; | ||
private static final Integer DEFAULT_INTEGER_EXAMPLE = 0; | ||
private static final String DEFAULT_BOOLEAN_EXAMPLE = "true"; | ||
private static final String DEFAULT_DATE_EXAMPLE = "\"2015-07-20\""; | ||
private static final String DEFAULT_DATE_TIME_EXAMPLE = "\"2015-07-20T15:49:04-07:00\""; | ||
private static final String DEFAULT_PASSWORD_EXAMPLE = "\"string-password\""; | ||
private static final String DEFAULT_BYTE_EXAMPLE = "\"YmFzZTY0LWV4YW1wbGU=\""; | ||
private static final String DEFAULT_DATE_EXAMPLE = "2015-07-20"; | ||
private static final String DEFAULT_DATE_TIME_EXAMPLE = "2015-07-20T15:49:04-07:00"; | ||
private static final String DEFAULT_PASSWORD_EXAMPLE = "string-password"; | ||
private static final String DEFAULT_BYTE_EXAMPLE = "YmFzZTY0LWV4YW1wbGU="; | ||
private static final String DEFAULT_BINARY_EXAMPLE = | ||
"\"0111010001100101011100110111010000101101011000100110100101101110011000010110010001111001\""; | ||
private static final String DEFAULT_STRING_EXAMPLE = "\"string\""; | ||
private static final String DEFAULT_EMAIL_EXAMPLE = "\"[email protected]\""; | ||
private static final String DEFAULT_UUID_EXAMPLE = "\"3fa85f64-5717-4562-b3fc-2c963f66afa6\""; | ||
"0111010001100101011100110111010000101101011000100110100101101110011000010110010001111001"; | ||
private static final String DEFAULT_STRING_EXAMPLE = "string"; | ||
private static final String DEFAULT_EMAIL_EXAMPLE = "[email protected]"; | ||
private static final String DEFAULT_UUID_EXAMPLE = "3fa85f64-5717-4562-b3fc-2c963f66afa6"; | ||
|
||
private static String DEFAULT_UNKNOWN_SCHEMA_EXAMPLE(String type) { | ||
return "\"unknown schema type: " + type + "\""; | ||
return "unknown schema type: " + type; | ||
} | ||
|
||
private static String DEFAULT_UNKNOWN_SCHEMA_STRING_EXAMPLE(String format) { | ||
return "\"unknown string schema format: " + format + "\""; | ||
return "unknown string schema format: " + format; | ||
} | ||
|
||
@Override | ||
|
@@ -65,13 +60,13 @@ static String buildSchema(Schema schema, Map<String, Schema> definitions) { | |
return buildSchemaInternal(schema, definitions, new HashSet<>()).toString(); | ||
} | ||
|
||
private static ObjectNode buildSchemaInternal(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) { | ||
ObjectNode exampleValue = ExampleJsonGenerator.getExampleValueFromSchemaAnnotation(schema); | ||
private static JsonNode buildSchemaInternal(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) { | ||
JsonNode exampleValue = ExampleJsonGenerator.getExampleValueFromSchemaAnnotation(schema); | ||
if (exampleValue != null) { | ||
return exampleValue; | ||
} | ||
|
||
ObjectNode schemaNode = objectMapper.createObjectNode(); | ||
JsonNode schemaNode = objectMapper.createObjectNode(); | ||
|
||
String ref = schema.get$ref(); | ||
if (ref != null) { | ||
|
@@ -84,53 +79,40 @@ private static ObjectNode buildSchemaInternal(Schema schema, Map<String, Schema> | |
} | ||
|
||
String type = schema.getType(); | ||
switch (type) { | ||
case "array": | ||
// Handle array schema | ||
ObjectNode itemsNode = ExampleJsonGenerator.handleArraySchema(schema, definitions, visited); | ||
schemaNode.set("items", itemsNode); // Set the "items" property | ||
break; | ||
case "boolean": | ||
schemaNode.textNode(DEFAULT_BOOLEAN_EXAMPLE); | ||
break; | ||
case "integer": | ||
schemaNode.textNode(DEFAULT_INTEGER_EXAMPLE); | ||
break; | ||
case "number": | ||
schemaNode.textNode(DEFAULT_NUMBER_EXAMPLE); | ||
break; | ||
case "object": | ||
// Handle object schema | ||
ObjectNode objectNode = ExampleJsonGenerator.handleObject(schema, definitions, visited); | ||
schemaNode.set("object", objectNode); // Set the "properties" property | ||
break; | ||
case "string": | ||
// Handle string schema | ||
schemaNode.textNode(ExampleJsonGenerator.handleStringSchema(schema)); | ||
break; | ||
default: | ||
schemaNode.put("example", DEFAULT_UNKNOWN_SCHEMA_EXAMPLE(type)); | ||
} | ||
schemaNode = switch (type) { | ||
case "array" -> ExampleJsonGenerator.handleArraySchema(schema, definitions, visited); // Handle array schema | ||
case "boolean" -> BooleanNode.valueOf(Boolean.parseBoolean(DEFAULT_BOOLEAN_EXAMPLE)); | ||
case "integer" -> new IntNode(DEFAULT_INTEGER_EXAMPLE); | ||
case "number" -> new DoubleNode(DEFAULT_NUMBER_EXAMPLE); | ||
case "object" -> ExampleJsonGenerator.handleObject(schema, definitions, visited); // Handle object schema | ||
case "string" -> JsonNodeFactory.instance.textNode(handleStringSchema(schema)); // Handle string schema | ||
default -> JsonNodeFactory.instance.textNode(DEFAULT_UNKNOWN_SCHEMA_EXAMPLE(type));}; | ||
|
||
return schemaNode; | ||
} | ||
|
||
private static ObjectNode getExampleValueFromSchemaAnnotation(Schema schema) { | ||
private static JsonNode getExampleValueFromSchemaAnnotation(Schema schema) { | ||
Object exampleValue = schema.getExample(); | ||
|
||
// schema is a map of properties from a nested object, whose example cannot be inferred | ||
if (exampleValue == null) { | ||
return null; | ||
} | ||
|
||
// Create an ObjectNode to hold the example JSON | ||
ObjectNode exampleNode = objectMapper.createObjectNode(); | ||
JsonNode exampleNode = objectMapper.createObjectNode(); | ||
|
||
// Handle special types (i.e. map) with custom @Schema annotation and specified example value | ||
Object additionalProperties = schema.getAdditionalProperties(); | ||
if (additionalProperties instanceof StringSchema) { | ||
StringSchema additionalPropertiesSchema = (StringSchema) additionalProperties; | ||
Object exampleValueString = additionalPropertiesSchema.getExample(); | ||
if (exampleValueString != null) { | ||
exampleNode.set((String) exampleValueString, objectMapper.convertValue(exampleValue, JsonNode.class)); | ||
try { | ||
exampleNode = objectMapper.readTree(exampleValueString.toString()); | ||
} catch (JsonProcessingException ex) { | ||
log.debug("Unable to convert example to JSON: %s".formatted(exampleValue.toString()), ex); | ||
} | ||
return exampleNode; | ||
} | ||
} | ||
|
@@ -141,42 +123,43 @@ private static ObjectNode getExampleValueFromSchemaAnnotation(Schema schema) { | |
} | ||
|
||
// exampleValue is represented in their native type | ||
if (exampleValue instanceof Boolean || exampleValue instanceof Number) { | ||
exampleNode.set("example", objectMapper.convertValue(exampleValue, JsonNode.class)); | ||
/* | ||
JsonNode node = objectMapper.createObjectNode(); | ||
node = objectMapper.valueToTree("false"); | ||
return (ObjectNode) node; | ||
*/ | ||
|
||
return exampleNode; | ||
if (exampleValue instanceof Boolean) { | ||
return (Boolean) exampleValue ? BooleanNode.TRUE : BooleanNode.FALSE; | ||
} else if (exampleValue instanceof Number) { | ||
double doubleValue = ((Number) exampleValue).doubleValue(); | ||
|
||
// Check if it's an integer (whole number) | ||
if (doubleValue == (int) doubleValue) { | ||
return new IntNode((int) doubleValue); | ||
} | ||
|
||
return new DoubleNode(doubleValue); | ||
} | ||
|
||
try { | ||
// exampleValue (i.e. OffsetDateTime) is represented as string | ||
exampleNode.set("example", objectMapper.convertValue(exampleValue.toString(), JsonNode.class)); | ||
exampleNode = JsonNodeFactory.instance.textNode(exampleValue.toString()); | ||
} catch (IllegalArgumentException ex) { | ||
log.debug("Unable to convert example to JSON: %s".formatted(exampleValue.toString()), ex); | ||
} | ||
|
||
return exampleNode; | ||
} | ||
|
||
private static ObjectNode handleArraySchema(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) { | ||
|
||
ObjectNode objectNode = objectMapper.createObjectNode(); | ||
private static ArrayNode handleArraySchema(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) { | ||
ArrayNode arrayNode = JsonNodeFactory.instance.arrayNode(); | ||
|
||
List<ObjectNode> list = Arrays.asList(buildSchemaInternal(schema.getItems(), definitions, visited)); | ||
List<JsonNode> list = Arrays.asList(buildSchemaInternal(schema.getItems(), definitions, visited)); | ||
|
||
objectNode.set("array", objectMapper.valueToTree(list)); | ||
for (JsonNode node : list) arrayNode.add(node); | ||
|
||
return objectNode; | ||
return arrayNode; | ||
} | ||
|
||
private static String handleStringSchema(Schema schema) { | ||
String firstEnumValue = getFirstEnumValue(schema); | ||
if (firstEnumValue != null) { | ||
return "\"" + firstEnumValue + "\""; | ||
return firstEnumValue; | ||
} | ||
|
||
String format = schema.getFormat(); | ||
|
@@ -208,7 +191,7 @@ private static String getFirstEnumValue(Schema schema) { | |
return null; | ||
} | ||
|
||
private static ObjectNode handleObject(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) { | ||
private static JsonNode handleObject(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) { | ||
|
||
Map<String, Schema> properties = schema.getProperties(); | ||
if (properties != null) { | ||
|