最後に私はこのために1つの汚い方法を見つけました。
親の概念を持つ汎用pojoであるJSONSchemaElement pojoを作成し、それに要素を追加します。
public class JSONSchemaElement {
private String elementName;
private JsonSchemaTagEnum.ELEMENT_TYPE elementType;
private String elementValue;
private String minItems;
private String maxItems;
private boolean hasChildren;
private List<JSONSchemaElement> children = new ArrayList<>();
public void addChildElement(JSONSchemaElement childElement) {
children.add(childElement);
}
/**
* @return the elementName
*/
public String getElementName() {
return elementName;
}
/**
* @param elementName
* the elementName to set
*/
public void setElementName(String elementName) {
this.elementName = elementName;
}
/**
* @return the elementType
*/
public JsonSchemaTagEnum.ELEMENT_TYPE getElementType() {
return elementType;
}
/**
* @param elementType
* the elementType to set
*/
public void setElementType(JsonSchemaTagEnum.ELEMENT_TYPE elementType) {
this.elementType = elementType;
}
/**
* @return the elementValue
*/
public String getElementValue() {
return elementValue;
}
/**
* @param elementValue
* the elementValue to set
*/
public void setElementValue(String elementValue) {
this.elementValue = elementValue;
}
/**
* @return the minItems
*/
public String getMinItems() {
return minItems;
}
/**
* @param minItems
* the minItems to set
*/
public void setMinItems(String minItems) {
this.minItems = minItems;
}
/**
* @return the maxItems
*/
public String getMaxItems() {
return maxItems;
}
/**
* @param maxItems
* the maxItems to set
*/
public void setMaxItems(String maxItems) {
this.maxItems = maxItems;
}
/**
* @return the hasChildren
*/
public boolean isHasChildren() {
return hasChildren;
}
/**
* @param hasChildren
* the hasChildren to set
*/
public void setHasChildren(boolean hasChildren) {
this.hasChildren = hasChildren;
}
/**
* @return the children
*/
public List<JSONSchemaElement> getChildren() {
return children;
}
/**
* @param children
* the children to set
*/
public void setChildren(List<JSONSchemaElement> children) {
this.children = children;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((children == null) ? 0 : children.hashCode());
result = prime * result + ((elementName == null) ? 0 : elementName.hashCode());
result = prime * result + ((elementType == null) ? 0 : elementType.hashCode());
result = prime * result + ((elementValue == null) ? 0 : elementValue.hashCode());
result = prime * result + (hasChildren ? 1231 : 1237);
result = prime * result + ((maxItems == null) ? 0 : maxItems.hashCode());
result = prime * result + ((minItems == null) ? 0 : minItems.hashCode());
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
JSONSchemaElement other = (JSONSchemaElement) obj;
if (children == null) {
if (other.children != null) {
return false;
}
}
else if (!children.equals(other.children)) {
return false;
}
if (elementName == null) {
if (other.elementName != null) {
return false;
}
}
else if (!elementName.equals(other.elementName)) {
return false;
}
if (elementType != other.elementType) {
return false;
}
if (elementValue == null) {
if (other.elementValue != null) {
return false;
}
}
else if (!elementValue.equals(other.elementValue)) {
return false;
}
if (hasChildren != other.hasChildren) {
return false;
}
if (maxItems == null) {
if (other.maxItems != null) {
return false;
}
}
else if (!maxItems.equals(other.maxItems)) {
return false;
}
if (minItems == null) {
if (other.minItems != null) {
return false;
}
}
else if (!minItems.equals(other.minItems)) {
return false;
}
return true;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JSONSchemaElement [elementName=" + elementName + ", elementType=" + elementType + ", elementValue="
+ elementValue + ", minItems=" + minItems + ", maxItems=" + maxItems + ", hasChildren=" + hasChildren
+ ", children=" + children + "]";
}
}
次に、以下のようなシングルトンクラスのメソッドを以下にparseJsonSchemaメソッドを呼び出します。ここでは、RootNodeを構築して、再帰的メソッドparseJsonSchemaに渡します。
JSONSchemaElement parentNode = null;
try {
JsonParser parser = new JsonParser();
Preconditions.checkState(StringUtils.isNotEmpty(jsonSchema), "JSON Schema Is NULL !!! ");
JsonObject parentObject = parser.parse(jsonSchema).getAsJsonObject();
parentNode = new JSONSchemaElement();
parentNode.setElementName(JsonSchemaTagEnum.ROOT_NODE.name());
parentNode.setHasChildren(true);
parentNode.setElementType(JsonSchemaTagEnum.ELEMENT_TYPE.COMPLEX_TYPE);
parseJSONSchema(parentObject, parentNode);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("After Parsing element->" + parentNode);
}
}
catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"-------------------- JSONSchemaUtility:fetchDecomposedJSONSchemaElementFromJsonSchema:: END ----------------------------------");
}
/**
*
* @param parentObject
* @param parentlement
*/
private void parseJSONSchema(JsonObject parentObject, JSONSchemaElement parentlement) {
Set<Map.Entry<String, JsonElement>> entries = parentObject.entrySet();
for (Map.Entry<String, JsonElement> entry : entries) {
JSONSchemaElement element = new JSONSchemaElement();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Entry Key->" + entry.getKey());
LOGGER.debug("Entry VALUE->" + entry.getValue());
}
if (entry.getValue().isJsonObject()) {
String key = entry.getKey();
element.setElementName(key.toUpperCase());
element.setElementType(JsonSchemaTagEnum.ELEMENT_TYPE.COMPLEX_TYPE);
element.setHasChildren(true);
if (!rejectKeyList.contains(entry.getKey().toUpperCase())) {
setPrimitiveType(entry, element);
}
/**
* create child
*/
parseJSONSchema(entry.getValue().getAsJsonObject(), element);
/**
* Pull Element from bottom to this key=> items->properties->actual element as ITEMS,PROPERTIES TAGS of
* JSON is not required
*/
element = pullChildFromBottomToTop(parentlement, element, key);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("************** Returning control back !!!!!!!!!!!");
}
}
else {
if (!JsonSchemaTagEnum.TYPE.name().equalsIgnoreCase(entry.getKey())) {
if (JsonSchemaTagEnum.MIN_ITEMS.name().equalsIgnoreCase(entry.getKey())) {
if (entry.getValue().isJsonPrimitive()) {
parentlement.setMinItems(entry.getValue().getAsString());
}
else if (entry.getValue().isJsonNull()) {
parentlement.setMinItems(entry.getValue().getAsJsonNull().toString());
}
}
else if (JsonSchemaTagEnum.MAX_ITEMS.name().equalsIgnoreCase(entry.getKey())) {
if (entry.getValue().isJsonPrimitive()) {
parentlement.setMaxItems(entry.getValue().getAsString());
}
else if (entry.getValue().isJsonNull()) {
parentlement.setMaxItems(entry.getValue().getAsJsonNull().toString());
}
}
else {
element.setElementName(entry.getKey().toUpperCase());
element.setElementType(JsonSchemaTagEnum.ELEMENT_TYPE.SIMPLE_TYPE);
if (entry.getValue().isJsonArray()) {
element.setElementValue(entry.getValue().getAsJsonArray().toString());
}
else if (entry.getValue().isJsonPrimitive()) {
element.setElementValue(entry.getValue().getAsString());
}
else if (entry.getValue().isJsonNull()) {
element.setElementValue(entry.getValue().getAsJsonNull().toString());
}
element.setHasChildren(false);
}
}
}
if (null != element && null != element.getElementName() && element.getElementName().length() > 0) {
parentlement.addChildElement(element);
}
}
}
/**
*
* @param parentlement
* @param element
* @param key
* @return
*/
private JSONSchemaElement pullChildFromBottomToTop(JSONSchemaElement parentlement, JSONSchemaElement element,
String key) {
if (JsonSchemaTagEnum.PROPERTIES.name().equalsIgnoreCase(key)
|| JsonSchemaTagEnum.ITEMS.name().equalsIgnoreCase(key)) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("For Properties Type key->" + element);
}
parentlement.setChildren(element.getChildren());
element.setChildren(null);
if (JsonSchemaTagEnum.ITEMS.name().equalsIgnoreCase(key)) {
if (null == parentlement.getMinItems()) {
parentlement.setMinItems(element.getMinItems());
}
if (null == parentlement.getMaxItems()) {
parentlement.setMaxItems(element.getMaxItems());
}
}
element = null;
}
return element;
}
/**
*
* @param entry
* @param element
*/
private void setPrimitiveType(Map.Entry<String, JsonElement> entry, JSONSchemaElement element) {
Gson gson = new Gson();
String jsonTypeCasted = gson.toJson(entry.getValue());
String formattedJsonString = (((jsonTypeCasted.replaceAll("\\{", "").trim()).replaceAll("\\}", "")
.trim()).replaceAll("\"", "")).trim();
String[] splitted = formattedJsonString.split(":");
if (splitted.length == 2) {
String validPrimitiveType = isValidJsonPrimitiveDataType(splitted[1]);
Preconditions.checkNotNull(validPrimitiveType,
"Data Type Mentioned In JSON Schema Is Not Supported By JSON: Valid Primitive Data Type Are NUMBER,STRING,BOOLEAN");
element.setElementValue(validPrimitiveType.toUpperCase());
element.setElementType(JsonSchemaTagEnum.ELEMENT_TYPE.SIMPLE_TYPE);
element.setHasChildren(false);
}
gson = null;
}
private String isValidJsonPrimitiveDataType(String inputPrimitiveType) {
String jsonPrimitiveDataType = null;
if (JSON_DATA_TYPE.STRING.toString().equalsIgnoreCase(inputPrimitiveType)) {
jsonPrimitiveDataType = JSON_DATA_TYPE.STRING.toString();
}
else if (JSON_DATA_TYPE.NUMBER.toString().equalsIgnoreCase(inputPrimitiveType)) {
jsonPrimitiveDataType = JSON_DATA_TYPE.NUMBER.toString();
}
else if (JSON_DATA_TYPE.BOOLEAN.toString().equalsIgnoreCase(inputPrimitiveType)) {
jsonPrimitiveDataType = JSON_DATA_TYPE.BOOLEAN.toString();
}
else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("This Data Type Is Not Supproted in JSON->" + inputPrimitiveType);
}
jsonPrimitiveDataType = null;
}
return jsonPrimitiveDataType;
}
}