Skip to content

Commit

Permalink
Refactored ExampleJsonGenerator.java internal methods to return Objec…
Browse files Browse the repository at this point in the history
…tNode objects
  • Loading branch information
dipeshsingh253 committed Oct 8, 2023
1 parent 65b49bd commit 6e0c6bf
Showing 1 changed file with 70 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package io.github.stavshamir.springwolf.schemas.example;

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.util.RawValue;
Expand Down Expand Up @@ -61,15 +62,17 @@ public Object fromSchema(Schema schema, Map<String, Schema> definitions) {
}

static String buildSchema(Schema schema, Map<String, Schema> definitions) {
return buildSchemaInternal(schema, definitions, new HashSet<>());
return buildSchemaInternal(schema, definitions, new HashSet<>()).toString();
}

private static String buildSchemaInternal(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) {
String exampleValue = ExampleJsonGenerator.getExampleValueFromSchemaAnnotation(schema);
private static ObjectNode buildSchemaInternal(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) {
ObjectNode exampleValue = ExampleJsonGenerator.getExampleValueFromSchemaAnnotation(schema);
if (exampleValue != null) {
return exampleValue;
}

ObjectNode schemaNode = objectMapper.createObjectNode();

String ref = schema.get$ref();
if (ref != null) {
String schemaName = StringUtils.substringAfterLast(ref, "/");
Expand All @@ -81,30 +84,54 @@ private static String buildSchemaInternal(Schema schema, Map<String, Schema> def
}

String type = schema.getType();
return switch (type) {
case "array" -> ExampleJsonGenerator.handleArraySchema(schema, definitions, visited);
case "boolean" -> DEFAULT_BOOLEAN_EXAMPLE;
case "integer" -> DEFAULT_INTEGER_EXAMPLE;
case "number" -> DEFAULT_NUMBER_EXAMPLE;
case "object" -> ExampleJsonGenerator.handleObject(schema, definitions, visited);
case "string" -> ExampleJsonGenerator.handleStringSchema(schema);
default -> DEFAULT_UNKNOWN_SCHEMA_EXAMPLE(type);
};
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));
}

return schemaNode;
}

private static String getExampleValueFromSchemaAnnotation(Schema schema) {
private static ObjectNode getExampleValueFromSchemaAnnotation(Schema schema) {
Object exampleValue = schema.getExample();
if (exampleValue == null) {
return null;
}

// Create an ObjectNode to hold the example JSON
ObjectNode 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) {
return (String) exampleValueString;
exampleNode.set((String) exampleValueString, objectMapper.convertValue(exampleValue, JsonNode.class));
return exampleNode;
}
}

Expand All @@ -115,21 +142,35 @@ private static String getExampleValueFromSchemaAnnotation(Schema schema) {

// exampleValue is represented in their native type
if (exampleValue instanceof Boolean || exampleValue instanceof Number) {
return exampleValue.toString();
exampleNode.set("example", objectMapper.convertValue(exampleValue, JsonNode.class));
/*
JsonNode node = objectMapper.createObjectNode();
node = objectMapper.valueToTree("false");
return (ObjectNode) node;
*/

return exampleNode;
}

try {
// exampleValue (i.e. OffsetDateTime) is represented as string
return objectMapper.writeValueAsString(exampleValue.toString());
} catch (JsonProcessingException ex) {
log.debug("Unable to convert example to string: %s".formatted(exampleValue.toString()), ex);
exampleNode.set("example", objectMapper.convertValue(exampleValue.toString(), JsonNode.class));
} catch (IllegalArgumentException ex) {
log.debug("Unable to convert example to JSON: %s".formatted(exampleValue.toString()), ex);
}
return "\"\"";

return exampleNode;
}

private static String handleArraySchema(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) {
return Arrays.asList(buildSchemaInternal(schema.getItems(), definitions, visited))
.toString();
private static ObjectNode handleArraySchema(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) {

ObjectNode objectNode = objectMapper.createObjectNode();

List<ObjectNode> list = Arrays.asList(buildSchemaInternal(schema.getItems(), definitions, visited));

objectNode.set("array", objectMapper.valueToTree(list));

return objectNode;
}

private static String handleStringSchema(Schema schema) {
Expand Down Expand Up @@ -167,13 +208,14 @@ private static String getFirstEnumValue(Schema schema) {
return null;
}

private static String handleObject(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) {
private static ObjectNode handleObject(Schema schema, Map<String, Schema> definitions, Set<Schema> visited) {

Map<String, Schema> properties = schema.getProperties();
if (properties != null) {

if (!visited.contains(schema)) {
visited.add(schema);
String example = handleObjectProperties(properties, definitions, visited);
ObjectNode example = handleObjectProperties(properties, definitions, visited);
visited.remove(schema);

return example;
Expand All @@ -195,11 +237,12 @@ private static String handleObject(Schema schema, Map<String, Schema> definition
}

// i.e. A MapSchema is type=object, but has properties=null
return "{}";
return objectMapper.createObjectNode();
}

private static String handleObjectProperties(
private static ObjectNode handleObjectProperties(
Map<String, Schema> properties, Map<String, Schema> definitions, Set<Schema> visited) {

ObjectNode objectNode = objectMapper.createObjectNode();

properties.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> {
Expand All @@ -208,6 +251,6 @@ private static String handleObjectProperties(
objectNode.putRawValue(propertyKey, propertyRawValue);
});

return objectNode.toString();
return objectNode;
}
}

0 comments on commit 6e0c6bf

Please sign in to comment.