首页 > 解决方案 > 如何打破具有嵌套对象的 JSON,以及如何创建一个可以传递多个项目的循环?

问题描述

我有 JSON 数据,我想将其转换为 CSV

我试过遵循这个如何将 JSON 转换为 CSV?但它仍然不起作用。

我知道我需要打破 JSON 中的嵌套对象以放入 CSV。

我担心的另一件事是我想要一个循环,其中多个项目(无论数量如何)可以通过代码,因为我的“ITEM”变量可能> 1

这是我的 JSON 样本

data_dict = 
[{'count': 19804,
  'next': {'limit': 1, 'offset': 1},
  'previous': None,
  'results': [{'company_name': 'Sunshine and Flowers',
               'delivery_address': '34 olive beach house, #01-22, 612345',
               'delivery_timeslot': {'bounds': '[)',
                                     'items': [{'id': 21668,
                                                'metadata': {},
                                                'name': 'Loose hair flowers',
                                                'quantity': 1,
                                                'removed': None},
                                               {'id': 21667,
                                                'metadata': {},
                                                'name': "Groom's Boutonniere",
                                                'quantity': 1,
                                                'removed': None},
                                               {'id': 21666,
                                                'metadata': {},
                                                'name': 'Bridal Bouquet',
                                                'quantity': 1,
                                                'removed': None}],
                                     'lower': '2019-12-06T10:00:00Z',
                                     'upper': '2019-12-06T13:00:00Z'}}]}]

这是我迄今为止尝试过的

import csv
import json    

dict_data = json.loads(dict_data)
f = csv.writer(open("test.csv", "wb+"))

for dict_data in dict_data:
    f.writerow([dict_data["count"],
                dict_data["next"]["limit"],
                dict_data["next"]["offset"],
                dict_data["results"]["company_name"],
                dict_data["results"]["delivery_address"],
                dict_data["results"]["delivery_timeslot"]["lower"]["'upper"]["'bounds"],
                dict_data["results"]["items"]["id"]["name"]["'quantity"]["metadata"]["removed"]])

我收到的错误消息是这样的

'not {!r}'.format(s.__class__.__name__)) TypeError: the JSON object must be str, bytes or bytearray, not 'list'

标签: python

解决方案


数据:

  • 问题中显示的数据是listof dicts,不是格式正确的json文件。
  • 我创建了一个文件,test.json格式如下:
[{'count': 19804,...,'results': []},
 {'count': 19805,...,'results': []},
 {'count': 19806,...,'results': []}]`
  • 数据与示例中给出的数据相同,重复 3 次。

读入数据ast.literal_eval

import ast

with open("test.json", "r") as f:
    data = ast.literal_eval(f.read())

用于pandas解包嵌套dicts

import pandas as pd
from pandas.io.json import json_normalize

df = json_normalize(data,
                    record_path=['results', 'delivery_timeslot', 'items'],
                    meta=[['next'],
                          ['count'],
                          ['results', 'company_name'],
                          ['results', 'delivery_timeslot', 'bounds'],
                          ['results', 'delivery_timeslot', 'lower'],
                          ['results', 'delivery_timeslot', 'upper']])

df[['next.limit', 'next.offset']] = df['next'].apply(pd.Series)
df.drop(columns=['next'], inplace=True)

数据框视图:

    id                 name  quantity removed metadata.lame metadata.horse  count  results.company_name results.delivery_timeslot.bounds results.delivery_timeslot.lower results.delivery_timeslot.upper  next.limit  next.offset
 21668   Loose hair flowers         1    None         Shit!          Shit!  19804  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
 21667  Groom's Boutonniere         1    None          This           This  19804  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
 21666       Bridal Bouquet         1    None            is             is  19804  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
 21668   Loose hair flowers         1    None             a              a  19805  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
 21667  Groom's Boutonniere         1    None        grassy         grassy  19805  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
 21666       Bridal Bouquet         1    None        knoll.         knoll.  19805  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
 21668   Loose hair flowers         1    None           NaN            NaN  19806  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
 21667  Groom's Boutonniere         1    None           NaN            NaN  19806  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
 21666       Bridal Bouquet         1    None           NaN            NaN  19806  Sunshine and Flowers                               [)            2019-12-06T10:00:00Z            2019-12-06T13:00:00Z           1            1
  • 根据需要重命名columns
    • df.rename(columns={'results.delivery_timeslot.lower': 'delivery_timeslot.lower'}, inplace=True)

将其保存到csv

df.to_csv('test.csv', index=False)

推荐阅读