2016-11-29 71 views
1

我有下面的Json Schema。如何使用Java對象表示下面的json模式?

{ 
     "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」。每個其他父節點都是一個處理程序。 「名稱」是具有「第一」和「最後」字段的處理程序。但對於年齡來說,由於沒有父鍵,所以應該有一個名爲「年齡」的處理程序,並且應該添加一個字段「年齡」。處理程序可以有處理程序。處理程序在其中有字段。下面是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; 
     } 

但是它覆蓋處理,當有處理程序中處理。此外,它看起來很笨拙,太多空分配和檢查。有沒有更好的方法來做這個方法已經做的事情?這是將模式作爲處理程序列表返回。任何幫助將非常感激。

+0

所以你放棄了json路徑? –

+0

哇你真的沒有什麼可以說我的答案...所以你爲什麼要求幫助... –

回答

1

首先,在我看來,這個問題更好的地方是Code Review論壇。

但是,讓你開始,我有幾點建議:

  1. 當你的直覺告訴你,代碼確實看起來「笨拙」,或者換句話說,不執行OO原則(或者甚至只是平原軟件開發的)在很大程度上。

  2. 我會首先查看if statememnt的長分支,使每個分支變成單獨的方法。像parseField()parseHandler(),也許還有其他這樣的代碼塊可以分離成單獨的方法。這將使parseJsonSchema()方法更具可讀性和可調試性(例如,這只是簡單的SW開發原理)

  3. 上述原則不僅適用於長碼塊的情況,也適用於短碼的情況爲清晰起見,將其隔離並隱藏詳細信息:if條件確定field是否爲FieldHandler。把它變成isField(Map.Entry<String, JsonNode> entry)方法。也許你現在看到爲什麼命名它field不是最好的選擇,如果它可以是FieldHandlerhandler1變量的註釋相同。它必須有一個更好理解的名字。

  4. 很高興您使用工廠來實例化字段。然而,除了調用concreate Field實現的構造函數之外,我沒有看到你的工廠還在做什麼,因爲json的所有解析和決策都在parseJsonSchema()中完成。作爲一個經驗法則,工廠應該爲每種返回的類型提供一種方法(沒有泛型)。因此,您的工廠正在返回各種Field s,那麼它應該只有createField()得到JsonNode並解析需要決定要實例化哪個實現。

  5. 要遵循的另一個OO原則是:在最內層的範圍聲明你的變量。objectNodeField只在處理字段的分支內部被訪問,所以把聲明放在這個分支的大括號內。不要在整個parseJsonSchema()的範圍內聲明它。這樣可以更容易地理解變量的範圍,並避免在適用範圍之外進行錯誤的訪問。

    現在,如果將分支變爲parseField()方法,則objectNodeField變量將成爲該新方法的本地變量。看看它如何使代碼在清晰度和穩定性方面更好?

  6. 當我們看着這個變量時,我在想爲什麼你的泛型類型爲ObjectNode,當它的具體差異是String,Integer和Boolean? StringField如何實現handle()方法Field接口並實際處理ObjectNode?國際海事組織,objectNodeField應宣佈Field<Object>或更好,Field<?>所以它可以承載上述類型。

  7. 很高興您使用遞歸來分析處理程序和字段的層次結構。但是,您真的認爲每次解析Json字符串,然後將樹重新打包回String以調用下一個遞歸是最好的方法嗎?

  8. 我可以繼續但不想壓倒你。最後一點,我認爲你應該熟悉Jackson將Json字符串解析爲多層次Map的功能。我認爲遍歷Json節點更容易。

+0

哇你真的沒有什麼可以說我的答案...所以你爲什麼要求幫助... –

+1

對不起爲延遲的回覆隊友。我已經完成了您所指定的更改。正如你所建議的,我一直在考慮用多層次地圖來轉換邏輯。我一直在等待讓你知道,一旦我完成了這一點:)本週末應該結束 – mayooran

+0

哦,我看到了,歡呼聲 –

相關問題