'How to obtain json schema from jsonpaths of all the required fields using java
Say the input is:
[{keyname: firstname, path:person.name.firstname,type:string},
{keyname:age, path:person.age,type:number}]
Then jsonschema should be generated from the json
{ person:{
name:{ firstname: guest },
age: 6
}}
I need the json schema
Solution 1:[1]
@Component public class SchemaUtil {
@Autowired
ObjectMapper mapper;
//Converts path of type -> $.eventMessage.phoneNumbers[:1].type to -> /eventMessage/phoneNumbers/0/type
public String pathConverter(String path) {
String newString=path.replace("$", "").replace(".", "/").replaceAll("\\[(.*?)\\]","/0");
return newString;
}
public String getSchema(List<SchemaPOJO> schemaList)
{
ObjectNode rootNode = mapper.createObjectNode();
StringBuilder output = new StringBuilder();
try
{
for(SchemaPOJO schema: schemaList)
{
String path = pathConverter(schema.getPath());
create(rootNode,path,schema.getDataType());
if(path.contains("/0/"))
{
int index1=path.indexOf("/0/");
while(index1 != -1)
{
String temp = path.substring(0,index1+1)+'1'+path.substring(index1+2);
create(rootNode,temp,schema.getDataType());
index1=path.indexOf("/0/",index1+1);
}
}
}
output.append("{\"$schema\":\"http://json-schema.org/draft-04/schema#\","
+ "\"type\": \"object\", \"properties\": {");
output.append(makeSchema(mapper.writeValueAsString(rootNode),null));
}
catch(Exception e)
{
return null;
}
List<String> keys = new ArrayList<>();
Iterator<String> iterator = rootNode.fieldNames();
iterator.forEachRemaining(e -> keys.add(e));
String inParams = String.join(",", keys.stream().map(key1 -> "\""+key1+"\"").collect(Collectors.toList()));
output.append(",\"required\":["+inParams+"]");
output.append("}");
return output.toString();
}
//Creates dummy values in json
private void create(ObjectNode rootNode, String path,String dataType)
{
switch(dataType)
{
case "string":createJson(rootNode, JsonPointer.compile(path), new TextNode("stringdummytext"));break;
case "integer":createJson(rootNode, JsonPointer.compile(path), new IntNode(65734));break;
case "float":createJson(rootNode, JsonPointer.compile(path), new FloatNode(124));break;
case "boolean":createJson(rootNode, JsonPointer.compile(path),BooleanNode.getFalse());break;
default:createJson(rootNode, JsonPointer.compile(path), new TextNode("stringdummytext"));break;
}
}
//Creates dummy json
private void createJson(ObjectNode node, JsonPointer pointer, JsonNode value) {
JsonPointer parentPointer = pointer.head();
JsonNode parentNode = node.at(parentPointer);
String fieldName = pointer.last().toString().substring(1);
if (parentNode.isMissingNode() || parentNode.isNull()) {
parentNode = StringUtils.isNumeric(fieldName) ? mapper.createArrayNode() : mapper.createObjectNode();
createJson(node,parentPointer, parentNode);
}
if (parentNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) parentNode;
int index = Integer.parseInt(fieldName);
for (int i = arrayNode.size(); i <= index; i++) {
arrayNode.addNull();
}
arrayNode.set(index, value);
} else if (parentNode.isObject()) {
((ObjectNode) parentNode).set(fieldName, value);
} else {
throw new IllegalArgumentException("`" + fieldName + "` can't be set for parent node `"
+ parentPointer + "` because parent is not a container but " + parentNode.getNodeType().name());
}
}
//Makes schema from dummy json
private String makeSchema(String json,JsonNodeType jsonNodeType) throws IOException
{
JsonNode jsonNode = mapper.readTree(json);
StringBuilder output = new StringBuilder();
for (Iterator<String> iterator = jsonNode.fieldNames(); iterator.hasNext();)
{
String fieldName = iterator.next();
JsonNodeType nodeType;
nodeType = jsonNode.get(fieldName).getNodeType();
output.append(convertNodeToStringSchemaNode(jsonNode, nodeType, fieldName));
output.append(",");
}
if( (jsonNodeType==null) || (jsonNodeType.name().equals("ARRAY")) || (jsonNodeType.name().equals("OBJECT")))
output.deleteCharAt(output.length()-1);
else if(jsonNode.getNodeType().name().equals("STRING"))
output.append("string\"");
else if(jsonNode.getNodeType().name().equals("NUMBER"))
output.append("integer\"");
output.append("}");
return output.toString();
}
//Util Method to create json schema
private String convertNodeToStringSchemaNode(JsonNode jsonNode, JsonNodeType nodeType, String key) throws IOException
{
StringBuilder result = new StringBuilder("\"" + key + "\": { \"type\": \"");
JsonNode node = null;
switch (nodeType) {
case ARRAY :
node = jsonNode.get(key).get(0);
result.append("array\", \"items\": [{ \"type\":\"");
if(node.getNodeType().name().equals("OBJECT"))
result.append("object\", \"properties\": { ");
result.append(makeSchema(node.toString(), node.getNodeType()));
if(node.getNodeType().name().equals("OBJECT"))
{
List<String> keys = new ArrayList<>();
Iterator<String> iterator = node.fieldNames();
iterator.forEachRemaining(e -> keys.add(e));
String inParams = String.join(",", keys.stream().map(key1 -> "\""+key1+"\"").collect(Collectors.toList()));
result.append(",\"required\":["+inParams+"]");
result.append("}");
}
result.append("]}");
break;
case BOOLEAN:
result.append("boolean\" }");
break;
case NUMBER:
result.append("integer\" }");
break;
case OBJECT:
node = jsonNode.get(key);
result.append("object\", \"properties\": {");
result.append(makeSchema(node.toString(), JsonNodeType.OBJECT));
List<String> keys = new ArrayList<>();
Iterator<String> iterator = node.fieldNames();
iterator.forEachRemaining(e -> keys.add(e));
String inParams = String.join(",", keys.stream().map(key1 -> "\""+key1+"\"").collect(Collectors.toList()));
result.append(",\"required\":["+inParams+"]");
result.append("}");
break;
case STRING:
result.append("string\" }");
break;
default:
result.append("string\" }");
}
return result.toString();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tanya Bhandari |