JSON в CSV — перейти на 4 уровня вглубь

#json

#json

Вопрос:

Я хотел бы извлечь только небольшую часть моего ответа JSON в CSV-файл. Однако мне нужно перейти на 4 уровня в глубину, и в настоящее время я могу перейти только на 3 уровня в глубину. Моя цель — иметь файл .csv с 3 столбцами campaign_id , campaign_name , cost_per_click и 3 строками для каждой из моих кампаний.

Оригинальный JSON

 {
   "318429215527453": {
      "conversion_events": {
         "data": [
            {
               "id": "djdfhdf",
               "name": "Total",
               "cost": 328.14,
               "metrics_breakdown": {
                  "data": [
                     {
                        "campaign_id": 2364,
                        "campaign_name": "uk",
                        "cost_per_click": 1345
                     },
                     {
                        "campaign_id": 7483,
                        "campaign_name": "fr",
                        "cost_per_click": 756
                     },
                     {
                        "campaign_id": 8374,
                        "campaign_name": "spain",
                        "cost_per_click": 545
                     },
                     {
                        "campaign_id": 2431,
                        "campaign_name": "ge",
                        "cost_per_click": 321
                     }
                  ],
                  "paging": {
                     "cursors": {
                        "after": "MjUZD"
                     },
                     "next": "https://graph.facebook.com/v9.0/xxxx"
                  }
               }
            }
         ],
         "summary": {
            "count": 1,
            "metric_date_range": {
               "date_range": {
                  "begin_date": "2021-01-09T00:00:00 0100",
                  "end_date": "2021-02-08T00:00:00 0100",
                  "time_zone": "Europe/Paris"
               },
               "prior_period_date_range": {
                  "begin_date": "2020-12-10T00:00:00 0100",
                  "end_date": "2021-01-09T00:00:00 0100"
               }
            }
         }
      },
      "id": "xxx"
   }
}
 

reformated.py

 import json

with open('campaigns.json') as json_file:
    data = json.load(json_file)

reformated_json = data['318429215527453']['conversion_events']['data']

with open('data.json', 'w') as outfile:
    json.dump(reformated_json, outfile)
 

Я пытался добавить ['metrics_breakdown'] или другой ['data'] в конце reformated_json , но я получаю TypeError: list indices must be integers or slices, not str.

         {
           "id": "djdfhdf",
           "name": "Total",
           "cost": 328.14,
           "metrics_breakdown": {
              "data": [
                 {
                    "campaign_id": 2364,
                    "campaign_name": "uk",
                    "cost_per_click": 1345,
                 },
                 {
                    "campaign_id": 7483,
                    "campaign_name": "fr",
                    "cost_per_click": 756,
                 },
                 {
                    "campaign_id": 8374,
                    "campaign_name": "spain",
                    "cost_per_click": 545,
                 },
                 {
                    "campaign_id": 2431,
                    "campaign_name": "ge",
                    "cost_per_click": 321,
                 },
              ],
              "paging": {
                 "cursors": {
                    "after": "MjUZD"
                 },
                 "next": "https://graph.facebook.com/v9.0/xxxx"
              }
           }
        }
     ]
 

Ответ №1:

 import csv
import json
from typing import Dict, List, Union # typing for easy development

# read json function
def read_json(json_path: str) -> Union[Dict, List]:
    with open(json_path, 'r') as file_io:
        return json.load(file_io)

# write csv function
def write_csv(data: List[Dict], csv_path: str) -> None:
    with open(csv_path, 'w') as file:
        fieldnames = set().union(*data)
        writer = csv.DictWriter(file, fieldnames=fieldnames,
                                lineterminator='n')
        writer.writeheader()
        writer.writerows(data)

# parse campaigns using a comprehension
def parse_campaigns(data: Dict) -> List[Dict]:
    return [row
            for value in data.values() # first level (conversion events)
            for root_data in value['conversion_events']['data'] # conversion events/data
            for row in root_data['metrics_breakdown']['data']] # data/metrics_breakdown/data

json_data = read_json('./campaigns.json')
campaign_data = parse_campaigns(json_data)
write_csv(campaign_data, 'campaigns.csv')
 

campaigns.csv (я скопировал данные в несколько объектов корневого словаря):

 cost_per_click,campaign_id,campaign_name
1345,2364,uk
756,7483,fr
545,8374,spain
321,2431,ge
1345,2364,uk
756,7483,fr
545,8374,spain
321,2431,ge

 

Ответ №2:

Первый data подраздел содержит список из одного элемента. Разыменование с [0] помощью, чтобы получить элемент, затем извлеките следующие слои ключей. Затем a DictWriter можно использовать для записи строк CSV:

 import json
import csv

with open('campaigns.json') as json_file:
    data = json.load(json_file)

items = data['318429215527453']['conversion_events']['data'][0]['metrics_breakdown']['data']

with open('data.csv', 'w', newline='') as outfile:
    w = csv.DictWriter(outfile,fieldnames=items[0].keys())
    w.writeheader()
    w.writerows(items)
 

Вывод:

 campaign_id,campaign_name,cost_per_click
2364,uk,1345
7483,fr,756
8374,spain,545
2431,ge,321