Awk
通過某種linux命令將巨大的舊json轉換成新的json格式?
我有這樣的原始json。一般來說,我的 json 非常大。為了使事情更簡單、更容易理解,我減少了條目。
{ "clientSettings":[ { "clientId":12345, "key":"abc", "value":false }, { "clientId":12345, "key":"def", "value":false }, { "clientId":12345, "key":"ghi", "value":false }, { "clientId":9876, "key":"lkmn", "value":false } ], "productSettings":[ { "productId":11, "key":"jkl", "value":true }, { "productId":11, "key":"mno", "value":true }, { "productId":12, "key":"jkl", "value":true }, { "productId":12, "key":"mno", "value":true } ], "customerSettings":[ { "key":"enableData", "value":false }, { "key":"minPriceValue", "value":"1.0" }, { "key":"presentData", "value":"AEGIS" } ], "thothTest":{ "9876":[ "K" ], "5431":[ "A", "L" ], "5123":[ "L" ] }, "osirisTest":{ "7678":[ "K" ] } }
- 在
clientSettings
json 數組中,我們有clientId's
它們的鍵/值。對於 singleclientId
,我可以有多個不同的鍵和值。例如 -12345
clientId
具有不同的鍵和值,如上所示。- 同樣的
productSettings
。- 但是因為
customerSettings
我只是有不同的鍵和值。- 因為
thothTest
而且osirisTest
我不需要做任何事情。我正在考慮重新設計上面的 json,這樣我就不必為每個鍵和值重複
clientId
和。productId
到目前為止,我的 json 很大,因為我有很多ids
相同但具有不同的鍵和值。所以我想出了下面新的 json 設計,它可以代表上面的 json -
{ "clientSettings":[ { "clientId":12345, "entries":[ { "key":"abc", "value":false }, { "key":"def", "value":false }, { "key":"ghi", "value":false } ] }, { "clientId":9876, "entries":[ { "key":"lkmn", "value":false } ] } ], "productSettings":[ { "productId":11, "entries":[ { "key":"jkl", "value":true }, { "key":"mno", "value":true } ] }, { "productId":12, "entries":[ { "key":"jkl", "value":true }, { "key":"mno", "value":true } ] } ], "customerSettings":[ { "key":"enableData", "value":false }, { "key":"minPriceValue", "value":"10.28" }, { "key":"presentData", "value":"AEGIS" } ], "thothTest":{ "9876":[ "K" ], "5431":[ "A", "L" ], "5123":[ "L" ] }, "osirisTest":{ "7678":[ "K" ] } }
問題陳述
現在給出一個舊的 json - 有沒有辦法通過某種腳本或 linux 命令將其轉換為新的 json 格式?由於我的 json 非常龐大,因此為每個 id 一個一個地做這件事需要一些時間,所以我們想如果我們可以通過一些 linux 命令將我的舊 json 轉換為新 json,那麼它可以加快這個過程。
JSON 處理最好使用理解 JSON 的工具來完成,例如
jq
Python。這是一個 Python 腳本,它可以滿足您的需要:#! /usr/bin/env python3 import json import sys from collections import defaultdict def combine(data, key, id_key): new_settings = defaultdict(list) for setting in data[key]: # Remove the ID from the setting and add it to the list of settings for that ID new_settings[setting.pop(id_key)].append(setting) # arrange the new settings in the desired format and overwrite the old settings data[key] = [{id_key: key, "entries": values} for key, values in new_settings.items()] data = json.load(sys.stdin) combine(data, "clientSettings", "clientId") combine(data, "productSettings", "productId") print(json.dumps(data))
將 JSON 輸入標準輸入並使用輸出:
$ ./process.py < old.json | jq { "clientSettings": [ { "clientId": 12345, "entries": [ { "key": "abc", "value": false }, { "key": "def", "value": false }, { "key": "ghi", "value": false } ] }, { "clientId": 9876, "entries": [ { "key": "lkmn", "value": false } ] } ], "productSettings": [ { "productId": 11, "entries": [ { "key": "jkl", "value": true }, { "key": "mno", "value": true } ] }, { "productId": 12, "entries": [ { "key": "jkl", "value": true }, { "key": "mno", "value": true } ] } ], "customerSettings": [ { "key": "enableData", "value": false }, { "key": "minPriceValue", "value": "1.0" }, { "key": "presentData", "value": "AEGIS" } ], "thothTest": { "9876": [ "K" ], "5431": [ "A", "L" ], "5123": [ "L" ] }, "osirisTest": { "7678": [ "K" ] } }
jq
您可以使用多種不同的方式重塑您的 JSON 。一種方法是分組.clientId
,並映射到一個新對象,該對象.clientId
將在分組數組之外。使用group_by
和map
:jq ' .clientSettings |= ( group_by(.clientId) | map( {clientId: .[0].clientId, entries: del(.[].clientId)} ) ) | .productSettings |= ( group_by(.productId) | map( {productId: .[0].productId, entries: del(.[].productId)} ) ) ' file.json
我剛剛為第二個對象複製粘貼了相同的命令。
如果您需要經常對大型 JSON 進行操作,我建議您熟悉並使用 mongodb 或任何類似的文件數據庫,例如參見手冊中的這個map-reduce 頁面,這就是您現在正在做的,沒有 reduce部分。所有這些操作都可以比解析 json 文件更快,語法類似於簡單的 javascript。