私はこのような生の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
キー/値があります。 Single の場合、clientId
複数の異なるキーと値を持つことができます。たとえば、12345
clientId
上記のように異なるキーと値を使用します。- 同様
productSettings
にについても同様である。 - しかし、
customerSettings
他のキーと値があるからです。 - なぜなら何も
thothTest
するosirisTest
必要がないからです。
clientId
各キーと値について、およびを繰り返す必要がないように、上記のjsonを再設計するつもりです。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を1つずつ処理するのに時間がかかりました。
答え1
jq
さまざまな方法でJSONを再構成できます。 1つの方法は、グループ化された配列の外側にある.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
2番目のオブジェクトに対して同じコマンドをコピーして貼り付けました。
大規模なJSONを頻繁に作業する必要がある場合は、mongodbまたは同様のドキュメントデータベースに精通して使用することをお勧めします。たとえば、次を参照してください。地図拡大ページマニュアルを見ると、縮小された部分なしで今やっていることがそうです。これらの操作はすべてjsonファイルを解析するよりも速く、構文は単純なjavascriptに似ています。
答え2
JSON処理は、JSON(Pythonなど)を理解するツールを使用して実行するのが最善ですjq
。必要なタスクを実行する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"
]
}
}
答え3
私が答えた解決策は基本的に次のとおりです。出版社:Sanasipしかし、ヘルパー関数を使用してgroupmap
配列の内容をグループ化してマッピングするように書き直されました。clientSettings
productSettings
def groupmap($key):
group_by(.[$key]) |
map( { ($key): first[$key], entries: map(del(.[$key])) } );
.clientSettings |= groupmap("clientId") |
.productSettings |= groupmap("productId")
これを使用すると、script
次のコマンドを使用して実行されます。
jq -f script file.json
以下は必須ではありませんが、複数の配列に「アイテムオブジェクト」(key
およびvalue
)が含まれているため、すべてのアイテムをkey: value
アイテムに変換できます。
def groupmap($key):
group_by(.[$key]) |
map( { ($key): first[$key], entries: map(del(.[$key])) } );
.clientSettings |= (groupmap("clientId") | map(.entries |= from_entries)) |
.productSettings |= (groupmap("productId") | map(.entries |= from_entries)) |
.customerSettings |= from_entries
これらの修正後の結果は次のようになります。
{
"clientSettings": [
{
"clientId": 9876,
"entries": { "lkmn": false }
},
{
"clientId": 12345,
"entries": { "abc": false, "def": false, "ghi": false }
}
],
"customerSettings": { "enableData": false, "minPriceValue": "1.0", "presentData": "AEGIS" },
"osirisTest": {
"7678": [ "K" ]
},
"productSettings": [
{
"entries": { "jkl": true, "mno": true },
"productId": 11
},
{
"entries": { "jkl": true, "mno": true },
"productId": 12
}
],
"thothTest": {
"5123": [ "L" ],
"5431": [ "A", "L" ],
"9876": [ "K" ]
}
}