Python中优雅处理JSON文件的方法实例
1. 引言
在本文中,我们将学习如何使用python读取、解析和编写json文件。
我们将讨论如何最好地处理简单的json文件以及嵌套的json文件,当然我们也将讨论如何访问json文件数据中的特定值。
2. 什么是json文件?
json(java script object notation)是一种流行的文件格式,主要用于在web应用程序中存储和传输数据。如果我们经常和数据打交道,那么一定或多或少遇到过json格式的文件,因此我们有必要来学习如何读取和写入json。
下图为常见的json文件结构的示例.
json结构看起来和python中的字典非常类似。需要注意的是,json格式通常是由key: 结对组成,其中key是字符串形式,value是字符串、数字、布尔值、数组、对象或null。
为了更直观的进行说明,在下图中我们以蓝色突出显示了所有的key,同时以橙色突出显示了所有的value。请注意,以下每组key/value间均使用逗号进行区分。
3. 使用python处理json文件
在python中内置了用于读取json文件的函数。以下给出几个如何将json文件解析为python对象的示例。
3.1. 将json文件读取为字典类型
首先我们需要导入 json库, 接着我们使用open函数来读取json文件,最后利用json.load()函数将json字符串转化为python字典形式.
就这么简单,代码如下:
import json with open('superheroes.json') as f: superherosquad = json.load(f) print(type(superherosquad)) # output: dict print(superherosquad.keys()) # output: dict_keys(['squadname', 'hometown', 'formed', 'secretbase', 'active', 'members'])
上述代码很简单很直观啦,唯一需要注意的是json库中有load()和loads()两个函数.
函数load()作用为读取json文件生成python对象函数loads()作用为读取json 字符串流生成python对象
我们可以将loads()函数中的字符s的含义理解成 load for strings.
3.2. 将json文件读取为pandas类型
当然我们也可以使用pandas库中的 read_json函数来读取对应的json文件,
代码如下:
import pandas as pd df = pd.read_json('superheroes.json')
运行结果如下:
需要注意的是使用pandas库不仅仅可以读取电脑本地磁盘上的json文件,也可以通过url读取网络上存放的文件.
代码如下:
df1 = pd.read_json('https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json')
3.3. 使用pandas读取嵌套json类型
我们有时候遇到的json文件是嵌套的,这经常会让读取工作变得有些困难. 其实嵌套json和python中的嵌套字典思想类似,即字典中嵌套字典.
我们观察上述例子中的member字段,其值也为字典类型,下图中我们使用缩进来展示嵌套结构。
设想一下,当我们将json文件加载到pandas数据框架中时,members列如下所示。每行包含一个字典。
接下来我们讨论两种实现方法,这两种方法中,我们可以解析数据,以便将每个键分解为单独的一列。
方案一
我们可以在members这一列上使用apply方法,代码如下:
df['members'].apply(pd.series)
上述代码执行后,members列会被拆分为4个新列,如下所示:
当然如果你想将上述拆分后的结果和之前的结果进行合并,可以使用pd.concat函数,
代码如下:
df = pd.concat([df['members'].apply(pd.series), df.drop('members', axis = 1)], axis = 1)
方案二
在pandas库中还有一个函数 json_normalize() ,它允许我们把嵌套的json展开。这是最简单的方法来解析嵌套的json了。
代码如下:
def test2(): with open('superheroes.json') as f: superherosquad = json.load(f) out = pd.json_normalize(superherosquad, record_path=['members'], meta=['squadname', 'hometown', 'formed', 'secretbase', 'active']) print(out)
上述代码中:
- record_path为我们希望拆分的列的名字
- meta为列名的list,为我们输出的次序
运行结果如下:
最后我们需要注意的是,我们可以在上述函数json_normalize中添加参数 meta_prefix,这样可以让我们对meta中的名字添加统一的前缀。
代码如下:
pd.json_normalize(superherosquad, record_path = ['members'], meta = ['squadname', 'hometown', 'formed', 'secretbase', 'active'], meta_prefix = 'members_')
运行结果如下:
3.4. 访问特定位置的数据
在python中我们可以通过key的名字或者下标来访问json文件中任意位置的数据。
比如,假设我们想知道我们的第二个超级英雄的秘密身份。即在下图中,需要访问特定位置的数据在下图中以紫色突出显示。
为了得到这个值,我们可以直接使用以下语句:
superherosquad['members'][1]['secretidentity']
从层次结构的顶部开始,由上往下,我们需要的第一个key是'members',因为它是我们需要访问的值所在的父节点。
在‘members'对应的键值中,我们看中括号,然后下标1表示list中的第二个成员。接着我们来看字段'secretidentity',如下所示:
将上述过程合并在一起,我们就可以得到我们特定位置出的值为'jane wilson'。
细心的同学可能已经注意到,我在上面的json片段中突出显示了两个蓝色的值。希望感兴趣的同学们可以作为练习来尝试访问这些值。欢迎在文章后面的评论区中分享你的代码。
3.5. 导出json
让我们编辑一下我们最后一位超级英雄,将其secretidentity从‘unknow'更改为‘will smith',接着将这个字典导出为json文件。这里我们将使用json.dump()函数将字典写入文件。
代码如下:
#update secret identity of eternal flame superherosquad['members'][2]['secretidentity'] = 'will smith' with open('superheroes.json', 'w') as file: json.dump(superherosquad, file)
上述代码运行后,我们打开文件superheroes.json,可以发现最后一名超级英雄的secretidentity已经由unknow变为了will smith.
当然,作为选择,我们也可以使用pandas中的to_json()函数,完成上述功能。
df.to_json('superheroes.json')
3.6. 格式化输出
我们有时候在终端直接打印json文件,通常会得到很不美观的输出,样例如下:
为了让其看起来更加美观,我们这里可以在函数json.dump中采用参数indent参数来控制输出格式,代码如下:
with open('superheroes.json', 'w') as file: json.dump(superherosquad, file, indent = 4)
结果输出如下,是不是看上去更加美观啦。。。
3.7. 输出字段排序
当然dump函数中含有字段sort_key,通过设置其值,可以控制输出时是否对key进行排序。需要注意所有的key包括嵌套的key都会进行排序。
样例如下:
with open('superheroes.json', 'w') as file: json.dump(superherosquad, file, indent = 4, sort_keys = true)
运行结果如下:
4.总结
最后,让我们对本文做一下回顾,总结如下:
- json文件通常由key:结对组成,这里key通常为字符串格式,value一般为字符串,数字,布尔,数组,对象或者null
- python有内置函数可以方便的读取json文件转化为python中的字典类型或者pandas可以处理的类型
- 使用pd.read_json()来读取简单的json,使用pd.json_normalize()来读取嵌套的json
- 我们可以通过key的名字或者下标来方便的获取json文件中特定位置的值
- python对象可以转化为json文件,同时可以对输出进行格式化输出以增加可读性
5.参考
到此这篇关于python中优雅处理json文件的文章就介绍到这了,更多相关python优雅处理json文件内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!