动态地从字典列表中创建嵌套的json对象

时间:2019-10-23 20:26:11

标签: python python-3.x list

我想将字典列表转换为嵌套的JSON。我想动态填充字段,我想将特定类别的所有信号分组。我尝试了不同的方法,但是无法生成所需的确切格式。需要一些逻辑帮助来生成JSON

我的输入

signal_list = [
    {'sig_id': 667, 'sig_name': 'RotorSpeed', 'Category': 'Gbox'},
    {'sig_id': 672, 'sig_name': 'GeneratorSpeed', 'Category': 'Genarator'},
    {'sig_id': 673, 'sig_name': 'NacelleSpeed', 'Category': 'Nacelle'},
    {'sig_id': 668, 'sig_name': 'RotorDirection', 'Category': 'Gbox'}
]

我尝试过的代码:

d = defaultdict(list)
for t in signals:
    field_list = d[t['Category']]
    new_d = {'sig_name': t['sig_name'], 'sig_id': t['sig_id'], 'Category': t['Category']}
    field_list.append(defaultdict(list, new_d))

当前输出

[
   {
      "Gbox":[
         {
            "sig_name":"RotorSpeed",
            "sig_id":667
         },
         {
            "sig_name":"RotorDirection",
            "sig_id":668
         }
      ]
   },
   {
      "Genarator":[
         {
            "sig_name":"GeneratorSpeed",
            "sig_id":672
         }
      ]
   },
   {
      "Signals":[
         {
            "sig_name":"NacelleSpeed",
            "SignalID":673
         }
      ]
   }
]

(必填)我的输出应如下所示

[
   {
      "Category":"Gbox",
      "Signals":[
         {
            "sig_name":"RotorSpeed",
            "sig_id":667
         },
         {
            "sig_name":"RotorDirection",
            "sig_id":668
         }
      ]
   },
   {
      "Category":"Genarator",
      "Signals":[
         {
            "sig_name":"GeneratorSpeed",
            "sig_id":672
         }
      ]
   },
   {
      "Category":"Nacelle",
      "Signals":[
         {
            "sig_name":"NacelleSpeed",
            "SignalID":673
         }
      ]
   }
]

1 个答案:

答案 0 :(得分:0)

请参阅itertools文档,尤其是groupby函数。

import json
import itertools

dta = signal_list = [
    {'sig_id': 667, 'sig_name': 'RotorSpeed', 'Category': 'Gbox'},
    {'sig_id': 672, 'sig_name': 'GeneratorSpeed', 'Category': 'Genarator'},
    {'sig_id': 673, 'sig_name': 'NacelleSpeed', 'Category': 'Nacelle'},
    {'sig_id': 668, 'sig_name': 'RotorDirection', 'Category': 'Gbox'}
]

# this key is simply to be used on each dictionary to get the 'Category'
key = lambda dct: dct.get('Category')

# group works best with a sorted iterable. So let's sort by "Category' since that's
# your grouping key.
a = itertools.groupby(sorted(dta, key=key), key)

# groupby returns a generator like object that has tuples of (key, value)
# the value is also a generator like object that just has each item from the iterable
# that matches your grouping key. To get all the items we just turn them into a list
b = [{"Category": k, "Signals": list(v)} for k,v in a]

# using json to print it out in a nice format
print(json.dumps(b, indent=1))

输出:

[
 {
  "Category": "Gbox",
  "Signals": [
   {
    "sig_id": 667,
    "sig_name": "RotorSpeed",
    "Category": "Gbox"
   },
   {
    "sig_id": 668,
    "sig_name": "RotorDirection",
    "Category": "Gbox"
   }
  ]
 },
 {
  "Category": "Genarator",
  "Signals": [
   {
    "sig_id": 672,
    "sig_name": "GeneratorSpeed",
    "Category": "Genarator"
   }
  ]
 },
 {
  "Category": "Nacelle",
  "Signals": [
   {
    "sig_id": 673,
    "sig_name": "NacelleSpeed",
    "Category": "Nacelle"
   }
  ]
 }
]

如果我的理解正确,您想从列表中的每个词典中删除“类别”键。你可以这样做。如果要删除多个键,只需编辑该功能并在内部进行某种循环:)

def remove_key(dct:dict, key):
    """
    Simply takes a dictionary, copies it and remove the key of interest
    from the copy and returns the copy.
    """
    # This function will be used in a list comprehension so it has to
    # return the dictionary and not just pop the key

    dct_ = dct.copy()
    _ = dct_.pop(key)

    return dct_

b = [{"Category": k, "Signals": [remove_key(dct, 'Category') for dct in v]} for k,v in a]

print(json.dumps(b, indent=1))

输出

[
 {
  "Category": "Gbox",
  "Signals": [
   {
    "sig_id": 667,
    "sig_name": "RotorSpeed"
   },
   {
    "sig_id": 668,
    "sig_name": "RotorDirection"
   }
  ]
 },
 {
  "Category": "Genarator",
  "Signals": [
   {
    "sig_id": 672,
    "sig_name": "GeneratorSpeed"
   }
  ]
 },
 {
  "Category": "Nacelle",
  "Signals": [
   {
    "sig_id": 673,
    "sig_name": "NacelleSpeed"
   }
  ]
 }
]