| 最近自己用python開發一些小東西,需要用json檔案儲存體些檔案屬性什麼的,但是發現用 json 包裡的 json.dump() 方法存json檔案的效果好醜……(其實是沒仔細看方法), 於是上網找了一份格式化json檔案的代碼,效果挺不錯,用了遞迴的思想,學習了一波並找到了其中一點小bug。然後,發現其實 json.dump() 方法其實只需要設定一個參數就達到格式化的效果了…… 下面介紹一下 json.dump() 和我 修改後的那份代碼。 json.dump() 直接把常用參數列一下好了也就是說在使用 json.dump() 的時候設定一下 indent 參數的值就好了。比如 json.dump(json_dict, f, indent=4) ,加與不加的區別如下: {"title_pinyin":"gywxw","title":"隔雲勿相望","url":"http://www.ty2016.net/book/gywxw/","description":"大學剛畢業,她嫁給了林安森可是結婚三年,電視上常看到他出席各種場合攜女相伴,她卻再沒再親眼見過他。"} { "title_pinyin":"gywxw", "title":"隔雲勿相望", "url":"http://www.ty2016.net/book/gywxw/", "description":"大學剛畢業,她嫁給了林安森可是結婚三年,電視上常看到他出席各種場合攜女相伴,她卻再沒再親眼見過他。" } 遞迴實現 直接粘過來了,不難理解,效果跟上邊是一樣的。 # -*- encoding: utf-8 -*- class JsonFormatter: def __init__(self, intend=4, name="", encoding="utf-8"): ’’’ intend: 縮排空格數 name: 檔案名稱 encoding: 檔案編碼 ’’’ self.name = name self.intend = intend self.encoding = encoding self.stack = [] self.obj = None self.source = self.get_source(name, self.encoding) self.prepare() @staticmethod def json_str(s): ’’’ 給字串套上雙引號 ’’’ return ’"’ + s + ’"’ @staticmethod def get_source(name, encoding="utf-8"): with open(name, ’r’, encoding=encoding) as f: # 當不給split函數傳遞任何參數時,分隔字元sep會採用任意形式的空白字元:空格、tab、換行、斷行符號以及換頁符 return ’’.join(f.read().split()) def prepare(self): try: # python對象和json格式還是略有不同 self.source = self.source.replace("null", "None").replace("true", "True").replace("false", "False") self.obj = eval(self.source) except: # json string 一定滿足python dict和list的組合 raise Exception(’Invalid json string!’) def line_intend(self, level=0): return ’\n’ + ’ ’ * self.intend * level def parse_dict(self,obj=None,intend_level=0): if intend_level == 0: # 這個判斷是為了防止檔案開頭出現空行 self.stack.append(’{’) else: self.stack.append(self.line_intend(intend_level)+’{’) intend_level += 1 i = 0 for key, value in obj.items(): key = self.json_str(str(key)) self.stack.append(self.line_intend(intend_level)+key+’:’) self.parse(value, intend_level) if i != len(obj.items())-1: # 這個處理是為了防止最後一對kv後面還有個逗號,這樣會造成json.load()函數無法讀取 self.stack.append(’,’) i += 1 self.stack.append(self.line_intend(intend_level-1)+’}’) def parse_list(self, obj=None, intend_level=0): if intend_level == 0: self.stack.append(’[’) else: self.stack.append(self.line_intend(intend_level)+’[’) intend_level += 1 for i, item in zip(range(0, len(obj)), obj): self.parse(item, intend_level) if i != len(obj)-1: self.stack.append(’,’) self.stack.append(self.line_intend(intend_level-1)+’]’) def parse(self, obj, intend_level=0): if obj is None: self.stack.append(’null’) elif obj is True: self.stack.append(’true’) elif obj is False: self.stack.append(’false’) elif isinstance(obj, (int, float)): self.stack.append(str(obj)) elif isinstance(obj, str): self.stack.append(self.json_str(obj)) elif isinstance(obj, (list, tuple)): self.parse_list(obj, intend_level) elif isinstance(obj, dict): self.parse_dict(obj, intend_level) else: raise Exception(’Invalid json type %s!’ % obj) def render(self): self.parse(self.obj, 0) res_file = self.name res = ’’.join(self.stack) with open(res_file, ’w’, encoding=self.encoding) as f: f.write(res) if __name__ == "__main__": jf = JsonFormatter(name="json.txt") jf.render()來源:孔天逸’Blog |