0や空白の扱いを決めれるようにしてみた
先日から作成中のCSV→JSON変換プログラムですがCSVに空白が含まれている場合や、値が0の項目をどう扱うのかというオプションを付けてみました。
今、以下のようなCSVファイルがあるとします。
ID, name, text, height, weight, sons, daughters 1, 夏子, どうも, 159.8, , 2, 1 2, 秋夫, こんにちは, 180.3, 78.5, 0, 1 3, 冬子, Hello, 163.5, , 3, 0
基本的には一行目をキーとし、2行目以降を値とするjsonに変換するのは従来どおりなのですが、上のCSVには空白や0の値が含まれています。そこでこれらの扱いを引数として設定できるようにjson出力部分を改造しました。
def jsonwriter(tFileName, tDict, digitize=True, ignore0=True, ignoreBlank=True, blankToNull=True): """write tDict to tFile as json. if digitize=True, digitizable values will be done. if digitize and ignore0 are both True, 0-value element is not written. if ignoreBlank=True, blank string ("") is not written. if ignoreBlank=False and blankToNull=True, blank string is written as null. """ tFile = codecs.open(tFileName, "w", "utf-8") tFile.write(u"[\n") #先頭の[ outerComFlg = u"" #2行目以降に改行とコンマを書き込むフラグ for line in tDict: tFile.write(outerComFlg + u" {") outerComFlg = u",\n" comFlg = u"" #行内の2要素目以降の先頭にコンマを書き込むフラグ for i, v in line.iteritems(): skip = False if digitize and bool(re.compile("^\d+(\.\d+)?\Z").match(v)): if ignore0 and float(v) == 0: skip = True else: if ignoreBlank and v == "": skip = True elif blankToNull and v == "": v = "null" else: v = '\"' + v + '\"' if not skip: tStr = comFlg + u'\"' + i + u'\":' + v tFile.write(tStr) comFlg = u"," tFile.write(u"}") tFile.write(u"\n]") tFile.close()
digitizeについては先日のエントリで書いた通りです。それ以外に
- ignore0 値が0の項目を書き出さずにとばす。digitizeがTrueの場合のみ有効。
- ignoreBlank 値が空の項目を書き出さずにとばす。
- blankToNull 値が空の項目をnullとして書き出す。ignoreBlankがFalseの場合のみ有効。ignoreBlankがFalseでこの値もFalseの場合は""として書き出される。
という3つのオプションを付けてみました。
デフォルトで上のCSVを書き出すと下のようになります。
[ {"ID":1,"name":"夏子","text":"どうも","height":159.8,"sons":2,"daughters":1}, {"ID":2,"name":"秋夫","text":"こんにちは","height":180.3,"weight":78.5,"daughters":1}, {"ID":3,"name":"冬子","text":"Hello","height":163.5,"sons":3} ]
ignore0、ignoreBlankが共にTrueなので夏子、冬子の体重や冬子の娘の項目は出力されません。jsonを利用するプログラム側に値がない場合は未記入か0であるというルールを用意すればやり取りするデータを小さくすることができそうです。
digitize=False, ignoreBlank=Falseだと
[ {"ID":"1","name":"夏子","text":"どうも","height":"159.8","weight":null,"sons":"2","daughters":"1"}, {"ID":"2","name":"秋夫","text":"こんにちは","height":"180.3","weight":"78.5","sons":"0","daughters":"1"}, {"ID":"3","name":"冬子","text":"Hello","height":"163.5","weight":null,"sons":"3","daughters":"0"} ]
といった感じです。
とりあえず出力部分はこれで完成です。