python - 在 Python 中扁平化/反规范化 Dict/Json

标签 python json flatten

嗨,我正在尝试将 JSON 反规范化/扁平化为字典,下面我有一种扁平化 JSON 的通用方法,下面的函数不知何故不处理嵌套的 JSON。目标是将嵌套的 dict/json 展平为 CSV 兼容对象。

我使用了以下代码:

def flatten(s):
    for i in s:
        if not isinstance(s[i], dict):
            yield (i, s[i])
        else:
            for b in flatten(s[i]):
                yield b


new_data = dict(list(flatten(mydict)))

print(new_data)

有了这个输入字典

mydict = "{
  'G_TRANSACTIONS': {
    'INVOICE_NUMBER': '31002',
    'TRANSACTION_CLASS': 'Invoice',
    'LIST_G_LINES': {
      'G_LINES': [
        {
          'LN_LINE_NUMBER': '1',
          'LN_LINE_TYPE': 'Line',
          'LN_DESCRIPTION': 'PKG980N-MAIN STREET 16C POCKET PLUGS',
          'LN_UNIT_OF_MEASURE': 'EA',
          'LN_QUANTITY': '3',
          'LN_NET_SELLING_PRICE': '200',
          'LN_NET_EXTENDED_AMOUNT': '600',
          'LIST_G_LINES_ITEM_NUMBER': {
            'G_LINES_ITEM_NUMBER': {
              'ITEM_NUMBER': '136864001'
            }
          }
        },
        {
          'LN_LINE_NUMBER': '1',
          'LN_LINE_TYPE': 'Other Line',
          'LN_DESCRIPTION': 'Johar Town Lahore',
          'LN_UNIT_OF_MEASURE': 'EA',
          'LN_QUANTITY': '3',
          'LN_NET_SELLING_PRICE': '200',
          'LN_NET_EXTENDED_AMOUNT': '999',
          'LIST_G_LINES_ITEM_NUMBER': {
            'G_LINES_ITEM_NUMBER': {
              'ITEM_NUMBER': '99999999'
            }
          }
        }
      ]
    },
    'TR_LN_AMOUNT': '600'
  }
}"

他们输出我得到的是:

{
  'INVOICE_NUMBER': '31002',
  'TRANSACTION_CLASS': 'Invoice',
  'G_LINES': [
    {
      'LN_LINE_NUMBER': '1',
      'LN_LINE_TYPE': 'Line',
      'LN_DESCRIPTION': 'PKG980N-MAIN STREET 16C POCKET PLUGS',
      'LN_UNIT_OF_MEASURE': 'EA',
      'LN_QUANTITY': '3',
      'LN_NET_SELLING_PRICE': '200',
      'LN_NET_EXTENDED_AMOUNT': '600',
      'LIST_G_LINES_ITEM_NUMBER': {
        'G_LINES_ITEM_NUMBER': {
          'ITEM_NUMBER': '136864001'
        }
      }
    },
    {
      'LN_LINE_NUMBER': '1',
      'LN_LINE_TYPE': 'Other Line',
      'LN_DESCRIPTION': 'Johar Town Lahore',
      'LN_UNIT_OF_MEASURE': 'EA',
      'LN_QUANTITY': '3',
      'LN_NET_SELLING_PRICE': '200',
      'LN_NET_EXTENDED_AMOUNT': '999',
      'LIST_G_LINES_ITEM_NUMBER': {
        'G_LINES_ITEM_NUMBER': {
          'ITEM_NUMBER': '99999999'
        }
      }
    }
  ],
  'TR_LN_AMOUNT': '600'
}

所需输出

{
  'INVOICE_NUMBER': '31002',
  'TRANSACTION_CLASS': 'Invoice',
  'LN_LINE_NUMBER': '1',
  'LN_LINE_TYPE': 'Line',
  'LN_DESCRIPTION': 'PKG980N-MAIN STREET 16C POCKET PLUGS',
  'LN_UNIT_OF_MEASURE': 'EA',
  'LN_QUANTITY': '3',
  'LN_NET_SELLING_PRICE': '200',
  'LN_NET_EXTENDED_AMOUNT': '600',
  'ITEM_NUMBER': '136864001',
  'TR_LN_AMOUNT': '600'
}
,
{
'INVOICE_NUMBER': '31002',
'TRANSACTION_CLASS': 'Invoice',
'LN_LINE_NUMBER': '1',
'LN_LINE_TYPE': 'Other Line',
'LN_DESCRIPTION': 'Johar Town Lahore',
'LN_UNIT_OF_MEASURE': 'EA',
'LN_QUANTITY': '3',
'LN_NET_SELLING_PRICE': '200',
'LN_NET_EXTENDED_AMOUNT': '999',
'ITEM_NUMBER': '99999999',
'TR_LN_AMOUNT': '600'
}

最佳答案

您可以尝试这个脚本,它会将 mydict 展平为正确的形式:

mydict = {
  'G_TRANSACTIONS': {
    'INVOICE_NUMBER': '31002',
    'TRANSACTION_CLASS': 'Invoice',
    'LIST_G_LINES': {
      'G_LINES': [
        {
          'LN_LINE_NUMBER': '1',
          'LN_LINE_TYPE': 'Line',
          'LN_DESCRIPTION': 'PKG980N-MAIN STREET 16C POCKET PLUGS',
          'LN_UNIT_OF_MEASURE': 'EA',
          'LN_QUANTITY': '3',
          'LN_NET_SELLING_PRICE': '200',
          'LN_NET_EXTENDED_AMOUNT': '600',
          'LIST_G_LINES_ITEM_NUMBER': {
            'G_LINES_ITEM_NUMBER': {
              'ITEM_NUMBER': '136864001'
            }
          }
        },
        {
          'LN_LINE_NUMBER': '1',
          'LN_LINE_TYPE': 'Other Line',
          'LN_DESCRIPTION': 'Johar Town Lahore',
          'LN_UNIT_OF_MEASURE': 'EA',
          'LN_QUANTITY': '3',
          'LN_NET_SELLING_PRICE': '200',
          'LN_NET_EXTENDED_AMOUNT': '999',
          'LIST_G_LINES_ITEM_NUMBER': {
            'G_LINES_ITEM_NUMBER': {
              'ITEM_NUMBER': '99999999'
            }
          }
        }
      ]
    },
    'TR_LN_AMOUNT': '600'
  }
}


def flatten(d, depth=0):
    rv = [({}, depth)]
    if isinstance(d, dict):
        for k, v in d.items():
            if not isinstance(v, dict) and not isinstance(v, list):
                for i in rv:
                    i[0][k] = v
            else:
                for (vv, _depth) in flatten(v,depth+1):
                    rv.append((rv[-1][0].copy(), _depth))
                    for kkk, vvv in vv.items():
                        rv[-1][0][kkk] = vvv
    elif isinstance(d, list):
        for v in d:
            rv.append((rv[-1][0].copy(), depth+1))
            for (vv, _) in flatten(v,depth+1):
                for kkk, vvv in vv.items():
                    rv[-1][0][kkk] = vvv
    for i, _depth in rv:
        yield i, _depth

from itertools import groupby

out = []
for v, g in groupby(sorted(flatten(mydict), key=lambda k: -k[1]), lambda k: k[1]):
    out.extend(i[0] for i in g)
    break

from pprint import pprint
for d in out:
    pprint(d)
    print('-' * 80)

打印:

{'INVOICE_NUMBER': '31002',
 'ITEM_NUMBER': '136864001',
 'LN_DESCRIPTION': 'PKG980N-MAIN STREET 16C POCKET PLUGS',
 'LN_LINE_NUMBER': '1',
 'LN_LINE_TYPE': 'Line',
 'LN_NET_EXTENDED_AMOUNT': '600',
 'LN_NET_SELLING_PRICE': '200',
 'LN_QUANTITY': '3',
 'LN_UNIT_OF_MEASURE': 'EA',
 'TRANSACTION_CLASS': 'Invoice',
 'TR_LN_AMOUNT': '600'}
--------------------------------------------------------------------------------
{'INVOICE_NUMBER': '31002',
 'ITEM_NUMBER': '99999999',
 'LN_DESCRIPTION': 'Johar Town Lahore',
 'LN_LINE_NUMBER': '1',
 'LN_LINE_TYPE': 'Other Line',
 'LN_NET_EXTENDED_AMOUNT': '999',
 'LN_NET_SELLING_PRICE': '200',
 'LN_QUANTITY': '3',
 'LN_UNIT_OF_MEASURE': 'EA',
 'TRANSACTION_CLASS': 'Invoice',
 'TR_LN_AMOUNT': '600'}
--------------------------------------------------------------------------------

关于python - 在 Python 中扁平化/反规范化 Dict/Json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57611070/

相关文章:

python - Pandas,根据现有的重复计数创建新列

python - 如何保留 xml 样式表?

javascript - 使用不同的 json 数据填充不同的选择框

javascript - 调用返回 JSON 的 PHP 会返回错误,但我可以看到响应

python - 从列表列表 Python 中的特定点开始循环

sql-server - 将记录平铺到值不为空的单行中

python - 无法解压列表中的元素

对象中的 PHP 和 Python 静态方法,两个不同的世界......?

python - 有没有一个python json库可以将json转换为模型对象,类似于google-gson?

C# 展平具有列表属性的对象列表