初投稿です。
JSONを編集しているときに、コメントをつけれたら、わかりやすくてミスも減るだろうと思ったので、Pythonでコメント付きのJSONを開くプログラム(というよりコメントを削除するプログラム)を作ってみました。
やっていることは、コメントの削除(ダブルクォーテーション内のコメントの記号は無視)をしたあと読み込むだけなので、CSVにも応用できます。
コメントの書き方は、C言語やC++と同じです。
ラインコメント → //ライン
ブロックコメント → /* ブロック */
追記: コメントできるYAMLというデータフォーマットがあるそうなので、それも選択肢の一つです。
#コード
文字列を一文字づつとってきて、コメント内なのか判定しています。ダブルクォーテーションに囲まれたコメント記号は無視することもできます。フラグをいっぱい使ってます。バグがあったら教えてください。
"""
コメントアウトするメソッド
一文字づつ処理して、コメント文は削除する
input:
string: コメントを含んだ文字列
quot_invalid: ダブルクォーテーションに囲まれた箇所のコメント記号を無視する
output: コメントを削除した文字列
"""
def comment_out(string, quot_invalid=True):
o_s = "" #コメントを削除した文字列
slash_start_flag = False #前の文字がスラッシュであるフラグ
slash_asterisk_delete_flag = False #ブロックコメント内であるフラグ
slash_asterisk_end_flag = False #ブロックコメント内で前の文字がアスタリスクであるフラグ
double_slash_delete_flag = False #ラインコメント内であるフラグ
in_dq_flag = False #ダブルクォーテーション内であるフラグ
for c in string:
if in_dq_flag and quot_invalid:
o_s += c
if c == '"':
in_dq_flag = False
elif slash_asterisk_end_flag:
if c == "/":
slash_asterisk_delete_flag = False
slash_asterisk_end_flag = False
if c == "*":
slash_asterisk_end_flag = True
elif slash_asterisk_delete_flag:
if c == "*":
slash_asterisk_end_flag = True
elif double_slash_delete_flag:
if c == "\n":
o_s += "\n"
double_slash_delete_flag = False
else: #コメント内ではないとき、または、コメントの始まりの'/'や'*'
if slash_start_flag:
if c == "*":
slash_asterisk_delete_flag = True
elif c == "/":
double_slash_delete_flag = True
else:
o_s += "/" + c
if quot_invalid and c == '"':
in_dq_flag = True
slash_start_flag = False
elif c == "/":
slash_start_flag = True
else:
o_s += c
if quot_invalid and c == '"':
in_dq_flag = True
#空白行を削除
return '\n'.join(filter(lambda x: x.strip(), o_s.split('\n')))
##正規表現を使ったコード
コメントで教えてもらったコードです。正規表現を使っていてコードが短くて理解しやすいです。上のメソッドのquot_invalidがFalseの場合と同じ出力を返します。ダブルクォーテーション内のコメント記号は無視されません。
import re
def comment_out(string):
# ブロックコメント除去
string = re.sub(r'/\*.*?\*/', r'', string, flags=re.DOTALL)
# ラインコメント除去
string = re.sub(r'//.*\n', r'\n', string)
return '\n'.join(filter(lambda x: x.strip(), string.split('\n')))
#実行結果
実行例です。comment_outを使うとコメントが消えます。ここでは第二引数にFalseを入れたときの結果です。
string = '''/*
JSONのサンプルです
*/
{
"name":"asasan",//名前です
"comment_test":"ここは残す/*ここは削除*/"
}
'''
print(comment_out(string,quot_invalid=False))
====実行結果====
{
"name":"asasan",
"comment_test":"ここは残す"
}
上の列では、ダブルクォーテーションで囲まれた箇所のコメント記号も無視されずに削除されました。ダブルクォーテーションで囲まれた箇所のコメント記号を無視する場合は第二引数にTrueを入れます。デフォルトではTrueです。
string = '''/*
JSONのサンプルです
*/
{
"name":"asasan",//名前です
"comment_test":"ここは残す/*ここも残す*/"
}
'''
print(comment_out(string,quot_invalid=True))
====実行結果====
{
"name":"asasan",
"comment_test":"ここは残す/*ここも残す*/"
}
ファイルから読み込み時は、下のようにすればjson_dataに値が格納されます。
import json
f = open('sample.json')
string = f.read()
f.close()
json_data = json.loads(comment_out(string))