首页 > 解决方案 > 如何以pythonic方式将原始json转换为所需格式

问题描述

我有来自某些服务的 json,其中每个值都是不同的行。

输入示例:

[
    {'author': 'alf', 'topic': 'topic1', 'lang': 'ge', 'value': 11},
    {'author': 'alf', 'topic': 'topic1', 'lang': 'ge', 'value': 22},
    {'author': 'bob', 'topic': 'topic1', 'lang': 'ge', 'value': 33},
    {'author': 'bob', 'topic': 'topic1', 'lang': 'ge', 'value': 44},
    {'author': 'alf', 'topic': 'topic1', 'lang': 'fr', 'value': 99},
    {'author': 'alf', 'topic': 'topic2', 'lang': 'ge', 'value': -20},
]

输出示例:

{
    'alf': {
        'topic1': [
            {'ge': [11, 22]},
            {'fr': [99]}
        ],
        'topic2': [
            {'ge': [-20]}
        ]
    },
    'bob': {
        'topic1': [
            {'ge': [33, 44]}
        ]
    }
}

所以基本上这是通过将指定键分组以将所有值收集到一个数组中的简单转换。

如果缺少所需的密钥,我通过检查和创建所需的密钥来完成此转换:

for entry in self._raw_data:
  parsed = {}
  author = entry["author"]
  topic = entry["topic"]
  lang = entry["lang"]
  value = entry["value"]
  if not parsed.get(author):
    parsed[author] = {}
  if not parsed[author].get(topic):
    parsed[author][topic] = []
  #etc

我敢肯定,这可以以更透明的方式完成。任何人都可以推荐一些东西吗?

标签: pythonjsonmapping

解决方案


如果您愿意将"topic"'s 值的类型从更改listdict,您可以使用.setdefault()

res = {}
for entry in raw_data:
    res.setdefault(entry['author'], {}).setdefault(entry["topic"], {}).setdefault(entry["lang"], []).append(entry["value"])

输出:

{
    "alf": {
        "topic1": {
            "fr": [99],
            "ge": [11, 22]
        },
        "topic2": {
            "ge": [-20]
        }
    },
    "bob": {
        "topic1": {
            "ge": [33, 44]
        }
    }
}

推荐阅读