2017-10-10 49 views
3

(很難想出總結問題的標題,因此可以隨意改進它)。使用jq解析存在於兩個列表中的鍵(即使它可能不存在於其中一個列表中)

我有以下內容的JSON文件:

{ 
    "Items": [ 
     { 
      "ID": { 
       "S": "ID_Complete" 
      }, 
      "oldProperties": { 
       "L": [ 
        { 
         "S": "[property_A : value_A_old]" 
        }, 
        { 
         "S": "[property_B : value_B_old]" 
        } 
       ] 
      }, 
      "newProperties": { 
       "L": [ 
        { 
         "S": "[property_A : value_A_new]" 
        }, 
        { 
         "S": "[property_B : value_B_new]" 
        } 
       ] 
      } 
     }, 
     { 
      "ID": { 
       "S": "ID_Incomplete" 
      }, 
      "oldProperties": { 
       "L": [ 
        { 
         "S": "[property_B : value_B_old]" 
        } 
       ] 
      }, 
      "newProperties": { 
       "L": [ 
        { 
         "S": "[property_A : value_A_new]" 
        }, 
        { 
         "S": "[property_B : value_B_new]" 
        } 
       ] 
      } 
     } 
    ] 
} 

我想要操縱以這樣的方式使用jq數據,對於在Items[]具有值的每個項目對於property_A(在newProperties list)生成一個輸出與相應的ID(見下面所希望的輸出)的字段而不管該性質在oldProperties具有列表中的值的。此外,如果property_A不會在oldProperties存在,我仍然需要場與null(或什麼是值得任何固定字符串)來填充。

所需的輸出:

{ 
    "id": "id_Complete", 
    "old": "[property_A : value_A_old]", 
    "new": "[property_A : value_A_new]" 
} 
{ 
    "id": "ID_Incomplete", 
    "old": null, 
    "new": "[property_A : value_A_new]" 
} 

注:即使property_A不會在oldProperties存在名單,其他屬性可以(也會)存在。

我現在面臨的問題是,我不能夠得到時所需的屬性不會在oldProperties存在列表的輸出。我現在jq命令如下:

jq -r '.Items[] | 
    { id:.ID.S, 
     old:.oldProperties.L[].S | select(. | contains("property_A")), 
     new:.newProperties.L[].S | select(. | contains("property_A")) }' 

這使得只有ID_Complete情況下,當我需要其他的爲好。

有什麼辦法可以使用這個工具來實現這個嗎?

在此先感謝。

回答

1

該過濾器產生所需的輸出。

def parse: capture("(?<key>\\w+)\\s*:\\s*(?<value>\\w+)") ; 
def print: "[\(.key) : \(.value)]"; 
def norm: [.[][][] | parse | select(.key=="property_A") | print][0]; 

    .Items 
| map({id:.ID.S, old:.oldProperties|norm, new:.newProperties|norm})[] 

樣品試驗(假定在filter.jq濾波器和數據在data.json

$ jq -M -f filter.jq data.json 
{ 
    "id": "ID_Complete", 
    "old": "[property_A : value_A_old]", 
    "new": "[property_A : value_A_new]" 
} 
{ 
    "id": "ID_Incomplete", 
    "old": null, 
    "new": "[property_A : value_A_new]" 
} 

Try it online!

+0

真棒回覆,謝謝。這個和其他的工作。然而,在接受之前,我會在已經存在的系統中嘗試使用它們,並且看看哪一個可以更好地適應它(因爲問題提供了一小部分數據的工作和修正示例)。 – Nacho

2

資料列表中的屬性似乎是一些對象的值。您可以將它們映射到對象中,然後區分對象,然後報告結果。

你可以做這樣的事情:

def make_object_from_properties: 
     [.L[].S | capture("\\[(?<key>\\w+) : (?<value>\\w+)\\]")] 
    | from_entries 
    ; 
def diff_objects($old; $new): 
     def _prop($key): select(has($key))[$key]; 
     ([($old | keys[]), ($new | keys[])] | unique) as $keys 
    | [ $keys[] as $k 
     | ({ value: $old | _prop($k) } // { none: true }) as $o 
     | ({ value: $new | _prop($k) } // { none: true }) as $n 
     | (if $o.none     then "add" 
      elif $n.none     then "remove" 
      elif $o.value != $n.value then "change" 
             else "same" 
      end) as $s 
     | { key: $k, status: $s, old: $o.value, new: $n.value } 
     ] 
    ; 
def diff_properties: 
     (.oldProperties | make_object_from_properties) as $old 
    | (.newProperties | make_object_from_properties) as $new 
    | diff_objects($old; $new) as $diff 
    | foreach $diff[] as $d ({ id: .ID.S }; 
      select($d.status != "same") 
     | .old = ((select(any("remove", "change"; . == $d.status)) | "[\($d.key) : \($d.old)]") // null) 
     | .new = ((select(any("add", "change"; . == $d.status)) | "[\($d.key) : \($d.new)]") // null) 
    ) 
    ; 
[.Items[] | diff_properties] 

我們得到以下的輸出:

[ 
    { 
    "id": "ID_Complete", 
    "old": "[property_A : value_A_old]", 
    "new": "[property_A : value_A_new]" 
    }, 
    { 
    "id": "ID_Complete", 
    "old": "[property_B : value_B_old]", 
    "new": "[property_B : value_B_new]" 
    }, 
    { 
    "id": "ID_Incomplete", 
    "old": null, 
    "new": "[property_A : value_A_new]" 
    }, 
    { 
    "id": "ID_Incomplete", 
    "old": "[property_B : value_B_old]", 
    "new": "[property_B : value_B_new]" 
    } 
] 

好像你的數據是在某種編碼格式的了。對於更強大的解決方案,您應該考慮定義一些功能來解碼它們。考慮如何找到here的方法。

+0

真棒回覆,謝謝。這個和其他的工作。然而,在接受之前,我會在已經存在的系統中嘗試使用它們,並且看看哪一個可以更好地適應它(因爲問題提供了一小部分數據的工作和修正示例)。 – Nacho

+0

經過多次測試後,我能夠更好地調整(以較少的更改)在我的系統的其他答案中提出的解決方案。這就是爲什麼我接受它,但是我想感謝你的詳細答案,這對於更好地理解jq的工作方式也很有價值。 – Nacho

相關問題