#22 ネストのあるjsonから文字列を抽出して置換したい
はじめに
とあるjsonに含まれる文字列をまとめて置換したい!ということで、正規表現を用いて文字列を置換する処理について、前後半にわけて備忘録としてまとめていきたいと思います。
今回はその後半として、実際にPythonを使ってjsonの文字列を抽出・置換し、内容を反映させたtxtファイルを作成します。
前回の記事のリンクを下に記載しております。興味のある方はぜひそちらもご覧いただければと思います。
前回記事:https://zenn.dev/nxted_sapporo/articles/e7cec2033b6b28
sample.jsonの確認
今回使用するjsonです。
{
"data": {
"id": {
"num": "1"
},
"group": {
"name": "ことわざ",
"folder": {
"nodes": [
{
"id": 1,
"name": "動物のことわざ",
"notes": {
"totalCount": 2,
"nodes": [
{
"id": 1,
"title": "猫に小判/豚に真珠/牛に経文",
"content": "01-価値のわからない者に価値のあるものを見せても、無意味だということ"
},
{
"id": 2,
"title": "雪に白鷺/闇夜のカラス",
"content": "02-目立たないことのたとえ"
}
]
}
},
{
"id": 2,
"name": "植物のことわざ",
"notes": {
"totalCount": 3,
"nodes": [
{
"id": 1,
"title": "矯めるなら若木のうち(類)鉄は熱いうちに打て",
"content": "01-早いうちに矯正しておくことが大切だということ"
},
{
"id": 2,
"title": "灯心で竹の根を掘る",
"content": "02-やっても無益なことのたとえ"
},
{
"id": 3,
"title": "御茶を挽く",
"content": "03-仕事がないこと"
}
]
}
}
]
}
}
}
}
このjsonから各title・contentを抽出し、txtファイルを作成します。
また、titleには「/」が含まれているものもありますが、こちらはファイル名として不適な記号であるため、「OR」に置換します。
また、contentには「01-」といった値が先頭にありますが、ファイルの内容からは省きたいと思います。
このjsonのポイントはネスト先で配列やハッシュが混ざっていることです。
まずは簡単に、配列とハッシュについておさらいしておきましょう。
配列
配列とは言語によってはリストと呼ばれたりもしますが、基本的には[]このスクエアブラケットで囲まれたものを指します。配列はインデックスと要素によって管理します。
引用:https://www.sejuku.net/blog/79079#index_id5
ハッシュ
ハッシュとは、JavaScriptではオブジェクトなど言語によって呼び方が違いますが、概念は同じで{}このカーリーブラケットで囲まれたもののことを示します。
(中略)ハッシュとは、keyとvalueを一セットとして扱う方法のことです。
引用:https://www.sejuku.net/blog/79079#index_id5
では実際に、任意の文字列を抽出していきましょう。
任意の文字列を抽出する
sample.jsonから「猫に小判/豚に真珠/牛に経文」「01-価値のわからない者に価値のあるものを見せても、無意味だということ」を抽出して変数に入れたものが以下になります。
ハッシュはkeyを、配列はインデックスを指定することでそれぞれ任意のvalue・要素を取り出すことができます。
#"猫に小判/豚に真珠/牛に経文"を抽出
beforeTitle = data["data"]["group"]["folder"]["nodes"][0]["notes"]["nodes"][0]["title"]
#"価値のわからない者に価値のあるものを見せても、無意味だということ"を抽出
content = data["data"]["group"]["folder"]["nodes"][0]["notes"]["nodes"][0]["content"]
任意の文字列を置換する
変数beforeTitleには抽出した文字列「猫に小判/豚に真珠/牛に経文」が格納されていますが、「/」が含まれているため、このままではファイル名として使用することができません。
そのため、以下の処理で「/」を「OR」に置換します。
#"猫に小判/豚に真珠/牛に経文"を"猫に小判OR豚に真珠OR牛に経文"に置換
afterTitle = beforeTitle.replace('/','OR')
また変数contentには抽出した文字列「01-価値のわからない者に価値のあるものを見せても、無意味だということ」が格納されていますが、今回は「01-」を削除した文字列としたいので、以下の処理で削除します。
#"01-価値のわからない者に価値のあるものを見せても、無意味だということ"を"価値のわからない者に価値のあるものを見せても、無意味だということ"に置換
import re
reContent = re.sub('[0-9]+-', '', content)
re.subメソッドは文字列を正規表現で置換する場合に用いるメソッドです。
第一引数に正規表現、第二引数に置換後の文字列、第三引数に置換される文字列を指定します。
ここでは、第二引数を「''」とすることで削除しています。
txtファイルを作成する
変数afterTitleをファイル名、変数reContentをファイルの中身としたtxtファイルを作成します。
txtファイルを作成する処理は以下の通りです。
f = open(afterTitle, 'w')
f.write(reContent)
f.close
afterTitleに格納されている値と同じ名前のファイルが存在しない場合、新しくファイルが作成されます。
ここでは「猫に小判OR豚に真珠OR牛に経文」という名前で「価値のわからない者に価値のあるものを見せても、無意味だということ」という内容のファイルが新たに作成されました。
現在、sample.jsonから任意のtitleを抽出する過程で、配列のインデックス番号を直接指定しています。そのため、他のtitleでファイルを作成するためには、都度インデックス番号を修正する必要があり、手間です。そこで、for文を利用してまとめてファイルを作成できるようにしてみました。
import json
import re
article = open( 'sample.json', 'r' )
data = json.load( article )
for groupCount in range(2)
for i in range(3):
totalCount = data["data"]["group"]["folder"]["nodes"][groupCount]["notes"]["totalCount"]
if i == totalCount:
break
beforeTitle = data["data"]["group"]["folder"]["nodes"][groupCount]["notes"]["nodes"][i]["title"]
afterTitle = beforeTitle.replace('/','OR')
content = data["data"]["group"]["folder"]["nodes"][groupCount]["notes"]["nodes"][i]["content"]
reContent = re.sub('[0-9]+-', '', content)
f = open(afterTitle, 'w')
f.write(reContent)
f.close
おわりに
前回の正規表現の知識を踏まえ、今回は多次元配列を持つjsonファイルの文字列を変換する処理を実際に作成していきました。抽出・置換・ファイル作成といった基本的な内容ではありますが、多次元配列の扱い方の理解に役立てていただけると幸いです。
以上です。閲覧ありがとうございました。
出典:
Discussion