I have this JSON schema:
{ "name":{ "first":{ "attributeValue":"firstName", "attributeType":1, "dataType":1 }, "last":{ "attributeValue":"lastName", "attributeType":1, "dataType":1 } }, "age":{ "attributeValue":"age", "attributeType":1, "dataType":2 }, "address":{ "number":{ "attributeValue":"number", "attributeType":1, "dataType":1 }, "street":{ "attributeValue":"street", "attributeType":1, "dataType":1 }, "city":{ "attributeValue":"city", "attributeType":1, "dataType":1 }, "country":{ "attributeValue":"country", "attributeType":1, "dataType":1 } }, "fullName":{ "attributeValue":"#firstName.concat(' ').concat(#lastName)", "attributeType":2, "dataType":1 } }
In here, each node that has attributeValue
, dataType
and attributeType
nodes are called Field
. Every other parent node is a handler. "name" is a handler which has "first" and "last" fields. But for age, since there is no parent key, there should be a handler created named "age" and a field "age" should be added to that. Handlers can have handlers. Handlers have fields in them.
Here is the Handler
object representation:
public interface Handler<T> { void addField(Field field); void addHandler(Handler handler); String getName(); List<Field> getFields(); T handle(T target); }
Here is the field representation:
public interface Field<T> { void setValue(String value); T getField(); String getFieldName(); }
Now I need to parse the json schema and return a list of handlers:
private List<Handler> parseJsonSchema(Handler handler, String jsonSchema) throws JSONMapperException { List<Handler> handlerList = new ArrayList<>(); boolean isParentLeaf = false; Field<ObjectNode> objectNodeField = null; try { JsonNode rootNode = objectMapper.readTree(jsonSchema); Iterator<Map.Entry<String, JsonNode>> childrenIterator = rootNode.fields(); while (childrenIterator.hasNext()) { Map.Entry<String, JsonNode> field = childrenIterator.next(); System.out.println("Key: " + field.getKey() + "\tValue:" + field.getValue()); if (field.getValue().has("attributeValue") && field.getValue().has("attributeType") && field.getValue().has("dataType")) { if (handler == null) { handler = jsonNodeHandlerFactory.create(field.getKey()); isParentLeaf = true; } JsonNode valueNode = field.getValue(); //String fieldName = valueNode.get("attributeValue").toString(); String fieldName = field.getKey(); String dataType = valueNode.get("dataType").toString(); switch (dataType) { case "1": objectNodeField = dataFieldFactory.createStringField(fieldName); break; case "2": objectNodeField = dataFieldFactory.createIntField(fieldName); break; case "3": objectNodeField = dataFieldFactory.createBooleanField(fieldName); break; default: break; } handler.addField(objectNodeField); if(isParentLeaf) { handlerList.add(handler); handler =null; } } else { handler = jsonNodeHandlerFactory.create(field.getKey()); List<Handler> handlers = parseJsonSchema(handler, field.getValue().toString()); for (Handler handler1 : handlers) { if(handler != null) { //means we already have a handler and we've come into another handler handler.addHandler(handler1); handlerList.add(handler); } else { handlerList.add(handler1); } } handler = null; } if ((handler != null && handler.getFields().size() == rootNode.size())) { handlerList.add(handler); } } } catch (IOException e) { logger.error(JSON_SCHEMA_PARSE_EXCEPTION, e); throw new JSONMapperException(JSON_SCHEMA_PARSE_EXCEPTION); } return handlerList; }
But it overrides handlers, when there are handlers within handlers. Also, it looks pretty clumsy with too many null
assignments and if
checks. Is there a better way to do what this method is already doing? That is, return the schema as a list of handlers.