如何使用Java Objects表示以下json模式?

时间:2016-11-29 23:37:46

标签: java json oop methods jackson

我有以下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
       }
    }

在这里,具有attributeValue,dataType和attributeType节点的每个节点都被称为“Field”。每个其他父节点都是一个处理程序。 “name”是具有“first”和“last”字段的处理程序。但是对于年龄,由于没有父键,因此应该创建一个名为“age”的处理程序,并且应该添加一个字段“age”。处理程序可以有处理程序。处理程序中包含字段。下面是Handler对象表示。

  public interface Handler<T> {
     void addField(Field field);
     void addHandler(Handler handler);
     String getName();
     List<Field> getFields();
     T handle(T target);
 }

以下是字段表示。

 public interface Field<T> {
     void setValue(String value);
     T getField();
     String getFieldName();
 }

现在我需要解析json模式并返回一个处理程序列表。以下是我的尝试。

 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;
        }

但是当处理程序中有处理程序时,它会覆盖处理程序。它也看起来非常笨拙,有太多的空分配和检查。有没有更好的方法来做这个方法已经做的事情?这将返回架构作为处理程序列表。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

首先,在我看来,这个问题的一个更好的地方是Code Review论坛。

但是,为了帮助您入门,我提供了一些提示:

  1. 正如你的直觉告诉你的那样,代码确实看起来很笨拙&#34;或者换句话说,没有在很大程度上实施OO原则(甚至只是简单的SW开发原则)。

  2. 我首先看一下if statememnt的长分支,使每个分支成为单独的方法。像parseField()parseHandler()之类的东西,也许还有其他这样的代码块可以被分离成单独的方法。这将使parseJsonSchema()方法更具可读性和可调试性(例如,这只是简单的SW开发原则)

  3. 上述原则不仅适用于长代码块,也适用于可以隔离的短代码,为了清晰起见隐藏细节:if条件决定field是否为Field HandlerisField(Map.Entry<String, JsonNode> entry)。将其变为field方法。也许您现在可以看到为什么命名Field不是最佳选择,如果它可以是Handlerhandler1parseJsonSchema()变量的注释相同。它必须有一个更易于理解的名称。

  4. 很高兴你使用工厂来实例化Fields。然而,除了调用构造函数进行concreate Field实现之外,我没有看到你的工厂还在做什么,因为json的所有解析和决策都是在Field中完成的。根据经验,工厂应该为每种返回类型(没有泛型)有一种方法。因此,您的工厂正在返回各种createField(),然后它应该只有JsonNode得到objectNodeField并解析它需要决定实例化哪个实现。

  5. 要遵循的另一个OO原则:尽可能在最内层范围内声明您的变量。 parseJsonSchema()只能在处理字段的分支内访问,因此请将声明放在此分支的大括号内。不要在整个parseField()的范围内声明它。这使得更容易理解变量的范围并避免在适用范围之外的错误访问。

    现在,如果将分支转换为objectNodeField方法,则ObjectNode变量将成为该新方法的本地变量。了解它如何使代码在清晰度和稳定性方面更好?

  6. 在我们查看这个变量的时候,我在想为什么在它的具体差异为String,Integer和Boolean时,为什么要使用它的泛型StringField? 如何handle()实现Field接口的ObjectNode方法并实际处理objectNodeField? IMO,Field<Object>应该被声明为Field<?>或更好,Jackson因此它可以托管上述类型。

  7. 很高兴您使用递归来解析处理程序和字段的层次结构。但是,您真的认为每次解析Json String,然后将树重新打包回String以调用下一个递归是最好的方法吗?

  8. 我可以继续但不想让你不堪重负。最后请注意,我认为您应该熟悉将Map解析为多层次结构 <web-app ...> <session-config> <session-timeout>20</session-timeout> </session-config> </web-app> 的Json字符串的功能。我认为遍历Json Nodes更容易。