JSONからCSVへの変換をする Pythonのプログラムを作成した | そう備忘録

JSONからCSVへの変換をする Pythonのプログラムを作成した

JSONからCSVへの変換プログラム

PythonにてJSON形式のファイルをCSVに変換した時の備忘録。

最初にpandasで一括変更を行ったのだが希望の形式にならなかったので1行ずつ読み込んで変換するプログラムに変更している。

実行環境

プログラムの実行環境は以下の通り。

OS

Windows10 Home 64Bit

Python

Python 3.6.8(Anaconda3 64 bit)

インプットJSON

読み込むJSONファイルは下記のデータとする。

[
    {
        "count_datetime": "2020-07-01T11:12:10.078347",
        "data": {
            "client_id": "client-10",
            "count_val": 61,
            "product_name": "製品名1セイヒンメイ"
        },
        "timestamp": 1593569530102
    },
    {
        "count_datetime": "2020-07-02T11:59:25.003013",
        "data": {
            "client_id": "client-16",
            "count_val": 3786,
            "product_name": "製品名2"
        },
        "timestamp": 1593658765022
    },
    {
        "count_datetime": "2020-07-03T11:54:00.070107",
        "data": {
            "client_id": "client-12",
            "count_val": 3578,
            "product_name": "製品名3"
        },
        "timestamp": 1593658440090
    }
]
  • データ件数は3件
  • ファイルUTF-8で保存※
  • client_id、count_val、product_nameはdataのネスト(入れ子)になっている
  • count_valは数値項目
  • product_nameには日本語項目

※ファイルをSHIFT-JISで作成してプログラム中でencoding=’shift_jis’を指定しても概ね動作したのだがpandasを使ったプログラムの場合、使用している日本語文字によっては変換エラーが出てしまった。

テキストファイルをUTF-8に変換して保存してプログラム中でもUTF-8で扱った方が安定して動作した様に思う。

プログラム

pandasを使ったプログラム

まずはpandasライブラリーを使ったプログラムでCSVに変換してみる。

# -*- coding: utf-8 -*-
"""
Created on Mon Jul 13 14:23:53 2020

JSONからCSV出力を行う
@author: Souichirou Kikuchi
"""
import argparse
import pandas as pd

if __name__ == '__main__':
    print('--- start program ---')
    # パラメータの取得
    parser = argparse.ArgumentParser(
            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
            '--injson', help='インプットのJSONファイル名', required=True)
    parser.add_argument(
            '--otcsv', help='アウトプットのCSVファイル名', required=True)
    args = parser.parse_args()

    try:
        df = pd.read_json(args.injson, encoding='utf_8')
        df.to_csv(args.otcsv, encoding='utf_8')       
    finally:
      pass

パラメーター

–injson

入力用のJSONファイル名を指定する

–otcsv

出力用のCSVファイル名を指定する

実行コマンド

以下のコマンドで実行する。

python json_to_csv_pandas.py --injson input_file.json --otcsv output_file.csv

変換結果

pandasを使ったプログラムでの変換結果

,count_datetime,data,timestamp
0,2020-07-01T11:12:10.078347,"{'client_id': 'client-10', 'count_val': 61, 'product_name': '製品名1セイヒンメイ'}",2020-07-01 02:12:10.102
1,2020-07-02T11:59:25.003013,"{'client_id': 'client-16', 'count_val': 3786, 'product_name': '製品名2'}",2020-07-02 02:59:25.022
2,2020-07-03T11:54:00.070107,"{'client_id': 'client-12', 'count_val': 3578, 'product_name': '製品名3'}",2020-07-02 02:54:00.090

プログラムはシンプルでほぼ意図した通りにCSV変換されたのだが若干やりたい事が違う。

dataの入れ子部分client_id、count_val、product_nameがヘッダーに来て欲しいのだが、データ行に入ってしまっている。

JSONは入れ子(ネスト)で項目を指定する事ができるので(当たり前だが)そのまま単純にCSVにする事ができていない。

1行づつ読み出す

JSONファイルを1行づつ読み出しながら各項目を取り出す事にした。

本当はもっと別にスマートなやり方がありそうだけれどもイマイチPythonを使いこなせていないので仕方がない。

# -*- coding: utf-8 -*-
"""
Created on Mon Jul 13 14:23:53 2020

JSONからCSV出力を行う
@author: Souichirou Kikuchi
"""
import argparse
import json
import csv

if __name__ == '__main__':
    print('--- start program ---')
    # パラメータの取得
    parser = argparse.ArgumentParser(
            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
            '--injson', help='インプットのJSONファイル名', required=True)
    parser.add_argument(
            '--otcsv', help='アウトプットのCSVファイル名', required=True)
    args = parser.parse_args()

    try:
        with open(args.injson, 'r', encoding='utf_8') as f:
            json_data = json.load(f) # JSONファイルの読み込み
            datas = [] 
            for idx in range(len(json_data)): # dataを取り出す
                count_datetime = json_data[idx]['count_datetime']
                client_id = json_data[idx]['data']['client_id']
                count_val = json_data[idx]['data']['count_val']
                product_name = json_data[idx]['data']['product_name']
                timestamp = json_data[idx]['timestamp']
                datas.append([count_datetime, client_id, count_val, product_name, timestamp])

        with open(args.otcsv, 'w', newline='') as csvFile: # 出力用CSVファイル
            out_csv = csv.writer(csvFile, delimiter=',',quotechar='"', quoting=csv.QUOTE_NONNUMERIC) # QUOTE_NONNUMERIC(全ての非数値項目をクォート)
            out_csv.writerow(['count_datetime', 'client_id', 'count_val', 'product_name', 'timestamp'])
            for data in datas:
                out_csv.writerow(data)
    finally:
      pass

変換結果

今度は希望通りの出力結果になった。

"count_datetime","client_id","count_val","product_name","timestamp"
"2020-07-01T11:12:10.078347","client-10",61,"製品名1",1593569530102
"2020-07-02T11:59:25.003013","client-16",3786,"製品名2",1593658765022
"2020-07-03T11:54:00.070107","client-12",3578,"製品名3",1593658440090

以上で今回の記事は終了とする。

最後に

この記事が何処かで誰かの役に立つことを願っている。

尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。

souichirou

やった事を忘れない為の備忘録 同じような事をやりたい人の参考になればと思ってブログにしてます。 主にレゴ、AWS(Amazon Web Services)、WordPress、Deep Learning、RaspberryPiに関するブログを書いています。 仕事では工場に協働ロボットの導入や中小企業へのAI/IoT導入のアドバイザーをやっています。 2019年7月にJDLA(一般社団法人 日本デイープラーニング協会)Deep Learning for GENERALに合格しました。 質問は記事一番下にあるコメントかメニュー上部の問い合わせからお願いします。

質問やコメントや励ましの言葉などを残す

名前、メール、サイト欄は任意です。
またメールアドレスは公開されません。