当前位置 博文首页 > Python 如何保存json文件并格式化

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

    作者:孔天逸 时间:2021-06-27 16:00

    背景

    最近自己搞些小东西,需要用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"  value="01"><br>
        用户:<a ></a><br>
        年龄:<a ></a><br>
        信息:<a ></a><br>
        <a ></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文件。希望能给大家一个参考,也希望大家多多支持站长博客。如有错误或未考虑完全的地方,望不吝赐教。

    js
    下一篇:没有了