Excelデータからjson作成の際、日時と日本語がうまく表示されないときは【python】

スポンサーリンク

やりたいこと

下記のようなエクセルファイル(data.xlsx)があったとします。

そこから、こういう形式のjsonファイル(output.json)をつくりたい。
ちなみに課題は、

  • 日時(yyyy-mm-ddThh:mm形式)をjson書き出しのときに扱えないよとエラーが出る。
  • 日本語が\uXXXX形式になってしまい、ちゃんと表示されない。
  • 数式の場合、数式ではなく値を取得してきて欲しい。
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "title": "芝浜",
        "description": "芝の浜で拾った財布の中に大金が…。",
        "timestamp": "2024-01-02T10:45"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "title": "浜野矩随",
        "description": "名人の息子も職人。だが全然うではよくなくて…。",
        "timestamp": "2024-01-10T12:30"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "title": "人情八百屋",
        "description": "八百屋が困窮する家族に出会い、野菜やお金をわけてあげるが…。",
        "timestamp": "2024-02-05T19:00"
      }
    }
  ]
スポンサーリンク

最終的にこうなったよ

import openpyxl
import json
import pandas as pd
from   datetime import date, datetime

###########jsonでdatetime型が扱えないので文字列に変換###########
# date, datetimeの変換関数
def json_serial(obj):
    # 日付型の場合→文字列にする
    if isinstance(obj, (datetime, date)):
        return obj.strftime("%Y-%m-%dT%H:%M")
    # 上記以外はサポート対象外.
    raise TypeError ("Type %s not serializable" % type(obj))

# datetime型を含むdict
item = { "dt" : datetime.now() }
#################################################

# Excel ファイルを読み込む
workbook = openpyxl.load_workbook(r"C:\Users\hogehoge\Desktop\data.xlsx", data_only=True)
worksheet = workbook.active

# ワークシートのデータをリストに格納
data = []
for row in worksheet.iter_rows(values_only=True):
    data.append(row)

# リストから DataFrame を作成
dataframe = pd.DataFrame(data, columns=data[0])

# 最初の行は列名なので削除
dataframe = dataframe.iloc[1:]

# DataFrame の各行のデータを取得し、JSON 形式のデータを生成する
features = []
for _, row in dataframe.iterrows():
    feature = {
      "type": "Feature",
      "properties": {
        "title": row["title"],
        "description": row["description"],
        "timestamp": row["timestamp"],
        
      },
    }
    features.append(feature)

# JSON データを生成する
data = {
    "type": "FeatureCollection",
    "features": features
}

# JSON ファイルに出力する
output_file = r"C:\Users\hogehoge\Desktop\output.json"
with open(output_file, "w", encoding="utf-8") as jsonfile:
    json.dump(data, jsonfile, indent=2, ensure_ascii=False, default=json_serial)

簡単に何をやったか解説していきます。

スポンサーリンク

①datetimeの型を文字列にしてjsonが書き出せるようにする

早速、openpyxl,json,pandasを使って実行してみたものの、
TypeError: Object of type datetime is not JSON serializable
というエラーが出てしましました。


どうもモジュール jsonはdatetimeに対応してないよ、ということみたいです。

ので、下記のような箇所を加えて対策。

###########jsonでdatetime型が扱えないので文字列に変換###########
# date, datetimeの変換関数
def json_serial(obj):
    # 日付型の場合→文字列にする
    if isinstance(obj, (datetime, date)):
        return obj.strftime("%Y-%m-%dT%H:%M")
    # 上記以外はサポート対象外.
    raise TypeError ("Type %s not serializable" % type(obj))

# datetime型を含むdict
item = { "dt" : datetime.now() }
#################################################
json.dump(data, jsonfile, indent=2, default=json_serial)

形式の調整したいときは、
“%Y-%m-%dT%H:%M”を”%Y-%m-%dT%H:%M:%S”にすれば、
2024-01-01T00:00:00
というように秒も出せそうですね。

こちらのページを参考にさせて頂きました。

スポンサーリンク

②jsonで日本語がうまく表示されない部分を解決

①を解決すると、jsonファイルは生成されるものの、こんな感じになります。

"title": "\u829d\u6d5c",
        "description": "\u829d\u306e\u6d5c\u3067\u62fe\u3063\u305f\u8ca1\u5e03\u306e\u4e2d\u306b\u5927\u91d1\u304c\u2026\u3002"

でも、絶望しなくてOK!(←一時した人)
jsonの書き出しを指示する部分(json.dump)に、ensure_ascii=Falseというオプションを加えれば解決します。

json.dump(data, jsonfile, indent=2, ensure_ascii=False, default=json_serial)

こちらのページを参考にさせて頂きました。

スポンサーリンク

③Excelから取得するのは関数ではなく、値にして欲しい

最後です。たとえばExcelが関数を使用して値を出しているとき、値を取得して欲しいのに、関数をそのまま取得されてしまいます。

そんなときは、openpyxl.load_workbook()部分にオプション(data_only=True)を加えれば、関数ではなく値を取ってきてくれます。

workbook = openpyxl.load_workbook(r"C:\Users\hogehoge\Desktop\data.xlsx", data_only=True)

こちらの記事を参考にさせて頂きました。

スポンサーリンク

最後に

浜野矩随と芝浜は五代目円楽が好きです。人情八百屋は立川梅春(ビートたけし)のが意外によかったです。

code初心者のつぶやき
スポンサーリンク
スポンサーリンク
シェアする

コメント