2017-02-09 54 views
1

我有一個JSON文檔從支持系統API中撤回。通過我的代碼,我想動態地提取預配置的字段,假設我的程序調用API時JSON可能會包含更多或更少的期望字段。使用Groovy動態分析JSON

我有一些可行的代碼,雖然它看起來非常複雜和低效。

這裏是JSON的作品,我很感興趣的一個片段:

{ 
    "rows": [ 
     { 
     "assignee_id": 1, 
     "created": "2017-01-25T14:13:19Z", 
     "custom_fields": [], 
     "fields": [], 
     "group_id": 2468, 
     "priority": "Low", 
     "requester_id": 2, 
     "status": "Open", 
     "subject": "Support request", 
     "ticket": { 
      "description": "Ticket descritpion", 
      "id": 1000, 
      "last_comment": { 
       "author_id": 2, 
       "body": "Arbitrary text", 
       "created_at": "2017-02-09T14:21:38Z", 
       "public": false 
      }, 
      "priority": "low", 
      "status": "open", 
      "subject": "Support request", 
      "type": "incident", 
      "url": "Arbitrary URL" 
     }, 
     "updated": "2017-02-09T14:21:38Z", 
     "updated_by_type": "Agent" 
     }, 
     { 
     "assignee_id": 1, 
     "created": "2017-02-09T14:00:18Z", 
     "custom_fields": [], 
     "fields": [], 
     "group_id": 3579, 
     "priority": "Normal", 
     "requester_id": 15, 
     "status": "Open", 
     "subject": "Change request", 
     "ticket": { 
      "description": "I want to change this...", 
      "id": 1001, 
      "last_comment": { 
       "author_id": 20, 
       "body": "I want to change the CSS on my website", 
       "created_at": "2017-02-09T14:12:12Z", 
       "public": true 
      }, 
      "priority": "normal", 
      "status": "open", 
      "subject": "Change request", 
      "type": "incident", 
      "url": "Arbitrary URL" 
     }, 
     "updated": "2017-02-09T14:12:12Z", 
     "updated_by_type": "Agent" 
     } 
    ] 
} 

我有一個ArrayList叫我建立wantedFields從配置來定義我想從拉出哪些信息該JSON:

["id","subject","requester_id","status","priority","updated","url"] 

的複雜性在於數據的API中複製的,我只希望在「行」一旦拔出的數據,與該數據的偏好適用。我的做法如下。這感覺就像我在重複代碼,但我無法真正看到如何更高效地完成這項工作。 JSON保存爲「viewAsJson」。

def ArrayList<Map<String,Object>> assignConfiguredFields(viewAsJson, wantedFields) { 
    //Pull out configured fields from JSON and store as Map to write as CSV later 
    ArrayList<Map<String,Object>> listOfDataToWrite = new ArrayList<Map<String,Object>>() 

    ArrayList<String> rowKeyList = new ArrayList<String>() 
    def validationRow = viewAsJson.rows.get(0) 
    //Compare one row object to config first 
    validationRow.each { k, v -> 
     if (wantedFields.contains(k)) { 
      wantedFields.remove(k) 
      rowKeyList.add(k) 
     } 
    } 

    ArrayList<String> ticketKeyList = new ArrayList<String>() 
    def validationTicket = viewAsJson.rows.ticket.get(0) 

    //Compare one ticket object to config first 
    validationTicket.each { k, v -> 
     if (wantedFields.contains(k)) { 
      wantedFields.remove(k) 
      ticketKeyList.add(k) 
     } 
    } 

    def rows = viewAsJson.rows 
    def tickets = viewAsJson.rows.ticket 

    //Pull matching ticket objects from JSON and store in Map 

    ArrayList<Map<String,Object>> tickList= new ArrayList<>() 
    ArrayList<Map<String,Object>> rowList= new ArrayList<>() 
    rows.each { row -> 
     Map<String,Object> rowMap = new HashMap<>() 
     row.each { k, v -> 
      if(rowKeyList.contains(k)) 
       rowMap.put(k,v) 
     } 
     rowList.add(rowMap) 
    } 

    tickets.each { ticket -> 
     Map<String,Object> ticketMap = new HashMap<>() 
     ticket.each { k, v -> 
      if(ticketKeyList.contains(k)) 
       ticketMap.put(k, v) 
     } 
     tickList.add(ticketMap) 
    } 

    for (int i = 0; i < rowList.size(); i++) { 
     HashMap<String,Object> dataMap = new HashMap<>() 
     dataMap.putAll(rowList.get(i)) 
     dataMap.putAll(tickList.get(i)) 
     listOfDataToWrite.add(dataMap) 
    } 

    println listOfDataToWrite 
    return listOfDataToWrite 
} 

我知道應該有一些驗證,如果wantedFields ArrayList仍然填充。我多次迭代這個代碼,這次我忘了重新添加。

+0

因此給出了Json以及按鍵[[「id」,「subject」,「requester_id」,「status」,「priority」,「updated」,「url」]'的鍵列表,你期望輸出是? –

+0

從示例JSON '[「id」:1000,「subject」:「支持請求」,「requester_id」:2,「status」:「open」,「priority」:「low」,「updated」:「 2017-02-09T14:21:38Z「,」url「:」任意網址「] 我已經意識到了代碼中的一個錯誤 - 雖然我現在正在解決這個問題。 – Donglecow

+0

好的,我現在已經修復了代碼。我期待它遍歷JSON並從「rows」數組中的每個項目中提取配置的數據。 EG: '[[「id」:1000,「subject」:「支持請求」,「requester_id」:2,「status」:「打開」,「優先級」:「低」,「更新」: 「2017-02-09T14:21:38 Z」,「url」:「任意URL」],[「id」:1001,「subject」:「變更請求」,「requester_id」:15,「status」: 「開放」,「優先」:「正常」,「更新」:「2017-02-09T14:12:12Z」,「網址」:「任意網址」]] – Donglecow

回答

1

我不知道你是否仍然需要這段代碼,但爲什麼不嘗試這樣的事情。 有翻譯地圖並通過它運行每一行。

Object tranverseMapForValue(Map source, String keysToTranverse, Integer location = 0){ 
    List keysToTranverseList = keysToTranverse.split(/\./) 
    tranverseMapForValue(source, keysToTranverseList, location) 
} 
Object tranverseMapForValue(Map source, List keysToTranverse, Integer location = 0){ 
    if(source.isEmpty() || keysToTranverse.isEmpty()){ 
     return null 
    } 

    String key = keysToTranverse[location] 
    if(source[key] instanceof Map){ 
     return tranverseMapForValue(source[key], keysToTranverse, location + 1) 
    } 
    else{ 
     return source[key] 
    } 
} 


Map translation = [ 
    "ticket.id": "id", 
    "ticket.subject": "subject", 
    "requester_id": "requester_id", 
    "ticket.status": "status", 
    "priority": "priority", 
    "updated": "updated", 
    "ticket.url": "url" 
] 

List rows = [] 

json.rows.each{ row -> 
    Map mapForRow = [:] 

    translation.each{ sourceKey, newKey -> 
     mapForRow << [(newKey): tranverseMapForValue(row, sourceKey)] 
    } 

    rows.add(mapForRow) 
} 
+0

我不再爲此工作,但我理解你所建議的過程,這很有意義。毫無疑問,它將在未來得心應手! – Donglecow