Python 如何保存json文件并格式化

背景

最近自己搞些小东西,需要用json文件存储些文件属性什么的,但是发现用json包里的json.dump()方法存json文件的效果好丑……(其实是没仔细看方法), 于是上网找了一份格式化json文件的代码,效果挺不错,用了递归的思想,学习了一波并找到了其中一点小bug。然后,发现其实json.dump()方法其实只需要设置一个参数就达到格式化的效果了……

下面介绍一下json.dump()和我修改后的那份代码,附原github地址

json.dump()

直接把常用参数列一下好了

参数名 解释
obj 要存入json文件的python对象
fp 文件句柄
ensure_ascii 设置为False的话才可以把中文以中文的形式存到文件里,否则会是'/xXX/xXX'这种
indent 缩进的空格数,设置为非零值时,就起到了格式化的效果,比较美观

也就是说在使用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()

后记

以后碰见问题不能这样焦躁了,先静下心来看看API吧,说不定答案就在里面。

补充:python如何将数据保存到本地json文件

之前做了dict字典的合并,这一篇会将dict数据转换成json格式的数据保存在本地,并在需要的时候读取显示。

将数据保存成.json文件:

@app.route('/', methods=['GET', 'POST'])def detail():    one = {'name': 'xiaozhi', 'age': 188}    mess1 = ['sss is  sss', 'aaa  aa aaaa']    two = {"mess1": mess1}    data = dict(one, **two)    jsonData = json.dumps(data)    fileObject = open('data.json', 'w')    fileObject.write(jsonData)    fileObject.close()    return jsonify({"success": 200, "data": data})

在浏览器输入URL后,json文件在本地创建,打开我们可以看到数据已经成功保存:

读取本地.json文件并解析显示:

如图,我们做一个点击事件,点击按钮读取.json文件,并将信息显示到对应的位置上

路由代码:

@app.route('/history', methods=['GET', 'POST'])def history():    data = json.loads(request.form.get('data'))    number = data['number']    print(number)    if number == '01':        file = 'data.json'        fb = open(file, 'r')        dicts = json.load(fb)        fb.close()        myjson = json.dumps(dicts)        return myjson    return 'no history'

前台页面展示交互展示代码:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>test</title>    <script src="{{ url_for('static', filename='js/jquery-1.7.1.min.js') }}"></script></head><body>    <input type="button" value="show log" οnclick="show()"/>    <input type="hidden" id="number" value="01"><br>    用户:<a id="user"></a><br>    年龄:<a id="age"></a><br>    信息:<a id="p0"></a><br>    <a id="p1"></a></body><script>     function show(){        var number= document.getElementById("number").value;        var data= {                data: JSON.stringify({                    'number': number                }),            }        $.ajax({            url:"{{ url_for('history') }}",            type:"post",            data:data,            dataType: 'json',            success:function(data){                $(user).text(data.name);                 $(age).text(data.age);                 for(var i=0;i<data.mess1.length;i++){                    $("#p"+i).text(data.mess1[i]);                }            },            error:function(e){                    alert("error");            }        })    }</script></html>

以上就可以简单的实现保存并读取本地json文件。希望能给大家一个参考,也希望大家多多支持 。如有错误或未考虑完全的地方,望不吝赐教。

相关文章

发表新评论