我心中的王者:Python-第24章 JSON资料

我心中的王者:Python-第24章 JSON资料

JSON是一种数据格式,由美国程序设计师Douglas Crockford创建的,JSON全名是JavaScript Object Notation,由JSON英文全文字义我们可以推敲JSON的缘由,最初是为JavaScript开发的。这种数据格式由于简单好用被大量应用在Web开发与大数据数据库(NoSQL),现在已成为一种著名数据格式,Python与许多程序语言同时采用与支持。也由此在使用Python设计程序时,可以将数据以JSON格式存储,与其他程序语言的设计师分享。

Python程序设计时需使用import json导入json模块。

24-1 认识json数据格式

json的数据格式有2种,分别是:

对象(object):一般用大括号{ }表示。

数组(array):一般用中括号[ ]表示。

24-1-1 对象(object)

在json中对象就是用“键-值(key:value)”方式配对存储,对象内容用左大括号“{”开始,右大括号“}”结束,键(key)和值(value)用“:”区隔,每一组键:值间以逗号“,”隔开,以下是取材自json.org的官方图说明。
在这里插入图片描述

在json格式中键(key)是一个字符串(string)。值可以是数值(number)、字符串(string)、布尔值(bool)、数组(array)或是null值。

例如:下列是对象的实例。

 {"Name":"Hung","Age":25}

使用json时需留意,键(key)必须是文字,例如下列是错误的实例。

 {"Name":"Hung", 25:"Key"}

在json格式中字符串需用双引号,同时在json文件内不可以有批注。

24-1-2 数组(array)

数组基本上是一系列的值(value)所组成,用左中括号“[”开始,右中括号“]”结束。各值之间用逗号“,”隔开,以下是取材自json.org的官方图说明。

在这里插入图片描述

数组的值可以是数值(number)、字符串(string)、布尔值(bool)、数组(array)或是null值。
在这里插入图片描述

24-1-3 json数据存在方式

前两节所述是json的数据格式定义,但是在Python中它存在方式是字符串(string)。

 ‘json数据'  # 可参考程序实例ch24_1.py的第3个输出

使用json模块执行将Python数据转成json字符串类型数据或json文件使用不同方法,下面24-2和24-3节将分别说明。

24-2 将Python应用在json字符串形式数据

本节主要说明json数据以字符串形式存在时的应用。

24-2-1 使用dumps( )将Python数据转成json格式

在json模块内有dumps( ),可以将Python数据转成json字符串格式,下列是转化对照表。
在这里插入图片描述

程序实例ch24_1.py:将Python的列表与元组数据转成json的数组数据的实例。

# ch24_1.py
import json

listNumbers = [5, 10, 20, 1]            # 列表数据
tupleNumbers = (1, 5, 10, 9)            # 元组资料
jsonData1 = json.dumps(listNumbers)     # 将列表数据转成json数据
jsonData2 = json.dumps(tupleNumbers)    # 将列表数据转成json数据
print("列表转换成json的数组", jsonData1)
print("元组转换成json的数组", jsonData2)
print("json数组在Python的数据类型 ", type(jsonData1))

执行结果

列表转换成json的数组 [5, 10, 20, 1]
元组转换成json的数组 [1, 5, 10, 9]
json数组在Python的数据类型  <class 'str'>

特别留意,上述笔者在第10行打印最终json在Python的数据类型,结果是以字符串方式存在。若以jsonData1为例,从上述执行结果我们可以了解,在Python内它的数据如下:

 ‘[5, 10, 20, 1]'

程序实例ch24_2.py:将Python由字典元素所组成的列表转成json数组,转换后原先字典元素变为json的对象。

# ch24_2.py
import json

listObj = [{'Name':'Peter', 'Age':25, 'Gender':'M'}]    # 列表数据元素是字典
jsonData = json.dumps(listObj)                          # 将列表数据转成json数据
print("列表转换成json的数组", jsonData)
print("json数组在Python的数据类型 ", type(jsonData))

执行结果

列表转换成json的数组 [{"Name": "Peter", "Age": 25, "Gender": "M"}]
json数组在Python的数据类型  <class 'str'>

读者应留意json对象的字符串是用双引号。

24-2-2 dumps( )的sort keys参数

Python的字典是无序的数据,使用dumps( )将Python数据转成json对象时,可以增加使用sort_keys=True,则可以将转成json格式的对象排序。

程序实例ch24_3.py:将字典转成json格式的对象,分别是未使用排序与使用排序。最后将未使用排序与使用排序的对象作比较判断是否相同,得到的是被视为不同对象。

# ch24_3.py
import json

dictObj = {'b':80, 'a':25, 'c':60}                  # 字典
jsonObj1 = json.dumps(dictObj)                      # 为排序将字典转成json对象
jsonObj2 = json.dumps(dictObj, sort_keys=True)      # 有排序将字典转成json对象
print("未用排序将字典转换成json的对象", jsonObj1)
print("使用排序将字典转换成json的对象", jsonObj2)
print("有排序与未排序对象是否相同    ", jsonObj1 == jsonObj2 )
print("json物件在Python的数据类型 ", type(jsonObj1))

执行结果

未用排序将字典转换成json的对象 {"b": 80, "a": 25, "c": 60}
使用排序将字典转换成json的对象 {"a": 25, "b": 80, "c": 60}
有排序与未排序对象是否相同     False
json物件在Python的数据类型  <class 'str'>

从上述执行结果得出json对象在Python的存放方式也是字符串。

24-2-3 dumps( )的indent参数

从ch24_3.py的执行结果可以看到数据不太容易阅读,特别是资料量如果更多的时候,在将Python的字典数据转成json格式的对象时,可以加上indent设定缩排json对象的键-值,让json对象可以更容易显示。

程序实例ch24_4.py:将Python的字典转成json格式对象时,设定缩排4个字符宽度。

# ch24_4.py
import json

dictObj = {'b':80, 'a':25, 'c':60}                      # 字典
jsonObj = json.dumps(dictObj, sort_keys=True, indent=4) # 用内缩呈现json对象
print(jsonObj)

执行结果

{
    "a": 25,
    "b": 80,
    "c": 60
}

24-2-4 使用loads( )将json格式数据转成Python的数据

在json模块内有loads( ),可以将json格式数据转成Python数据,下列是转化对照表。
在这里插入图片描述

程序实例ch24_5.py:将json的对象数据转成Python数据的实例,需留意在建立json数据时,需加上引号,因为json数据在Python内是以字符串形式存在。

# ch24_5.py
import json

jsonObj = '{"b":80, "a":25, "c":60}'    # json物件
dictObj = json.loads(jsonObj)           # 转成Python物件
print(dictObj)
print(type(dictObj))

执行结果

{'b': 80, 'a': 25, 'c': 60}
<class 'dict'>

从上述可以看到json对象返回Python数据时的数据类型。

24-3 将Python应用在json文件

我们在程序设计时,更重要的是将Python的资料以json格式存储,未来可以供其他不同的程序语言读取。或是使用Python读取其他语言以json格式存储的数据。

24-3-1 使用dump( )将Python数据转成json文件

在json模块内有dump( ),可以将Python数据转成json文件格式,这个文件格式的扩展名是json,下列将直接以程序实例解说dump( )的用法。

程序实例ch24_6.py:将一个字典数据,使用json格式存储在out24_6.json文件内。在这个程序实例中,dump( )方法的第一个参数是欲存储成json格式的数据,第二个参数是欲存储的文件对象。

# ch24_6.py
import json

dictObj = {'b':80, 'a':25, 'c':60}      
fn = 'out24_6.json'
with open(fn, 'w') as fnObj:
    json.dump(dictObj, fnObj)

执行结果 在目前工作文件夹可以新增json文件,文件名是out24_6.json。如果用记事本打开,可以得到下列结果。
在这里插入图片描述

24-3-2 使用load( )读取json文件

在json模块内有load( ),可以读取json文件,读完后这个json文件将被转换成Python的数据格式,下列将直接以程序实例解说dump( )的用法。

程序实例ch24_7.py:读取json文件out24_6.json,同时列出结果。

# ch24_7.py
import json
      
fn = 'out24_6.json'
with open(fn, 'r') as fnObj:
    data = json.load(fnObj)

print(data)
print(type(data))

执行结果

{'b': 80, 'a': 25, 'c': 60}
<class 'dict'>

24-4 简单的json文件应用

程序实例ch24_8.py:程序执行时会要求输入账号,然后列出所输入账号同时打印欢迎使用本系统。

# ch24_8.py
import json

fn = 'login.json'
login = input("请输入账号 : ")
with open(fn, 'w') as fnObj:
    json.dump(login, fnObj)
    print("%s! 欢迎使用本系统! " % login)

执行结果

请输入账号 : 晓波  
晓波! 欢迎使用本系统!

上述程序同时会将所输入的账号存入login.json文件内。

程序实例ch24_9.py:读取login.json的数据,同时输出“欢迎回来使用本系统”。

# ch24_9.py
import json

fn = 'login.json'
with open(fn, 'r') as fnObj:
    login = json.load(fnObj)
    print("%s! 欢迎回来使用本系统! " % login)

执行结果

晓波! 欢迎回来使用本系统! 

程序实例ch24_10.py:下列程序基本上是ch24_8.py和ch24_9.py的组合,如果第一次登录会要求输入账号然后将输入账号记录在login24_10.json文件内,如果不是第一次登录,会直接读取已经存在login24_10.json的账号,然后打印“欢迎回来”。这个程序用第7行是否能正常读取login24_10.json方式判断是否是第一次登录,如果这个文件不存在表示是第一次登录,将执行第8行except至12行的内容。如果这个文件已经存在,表示不是第一次登录,将执行第13行else:后面的内容。

# ch24_10.py
import json

fn = 'login24_10.json'
try:
    with open(fn) as fnObj:
        login = json.load(fnObj)   
except Exception:
    login = input("请输入账号 : ") 
    with open(fn, 'w') as fnObj:
        json.dump(login, fnObj)
        print("系统已经记录你的账号 ")
else:
    print("%s 欢迎回来" % login)

执行结果

andyyah 欢迎回来

24-5 世界人口数据的json文件

在本书ch24文件夹内有populations.json文件,这是一个非官方在2000年和2010年的人口统计数据,这一节笔者将一步一步讲解如何使用json数据文件。

24-5-1 认识人口统计的json文件

若是将这个文件用记事本打开,内容如下:
在这里插入图片描述

在网络上任何一个号称是真实统计的json数据,在用记事本打开后,初看一定是复杂的,读者碰上这个问题首先不要慌,同时分析数据的共通性,这样有助于未来程序的规划与设计。从上图基本上我们可以了解它的资料格式,这是一个列表,列表元素是字典,有些国家或地区只有2000年的资料,有些只有2010年的资料,有些则同时有这2个年度的数据,每个字典内有4个键-值,如下所示:

在这里插入图片描述

上述字段分别是国家或地区名称(Country Name)、国家代码(Country Code)、年份(Year)和人口数(numbers)。从上述文件我们应该注意到,人口数在我们日常生活理解应该是整数,可是这个数据是用字符串表达,另外,在非官方的统计数据中,难免会有错误,例如,上述国家或地区(这是全球人口统计)的2010年人口数据资料出现了小数点,这个需要我们用程序处理。

程序实例ch24_11.py:列出populations.json数据中的人口数据。

# ch24_11.py
import json

fn = 'populations.json'
with open(fn) as fnObj:
    getDatas = json.load(fnObj)                     # 读json档案

for getData in getDatas:
    if getData['Year'] == '2000':                   # 筛选2000年的数据
        countryName = getData['Country Name']      
        countryCode = getData['Country Code']       
        population = int(float(getData['Numbers']))
        print('代码 =', countryCode,
              '名称 =', countryName,
              '人口数 =', population)

执行结果

代码 = WLD 名称 = World 人口数 = 6117806174
代码 = AFG 名称 = Afghanistan 人口数 = 25951672
代码 = ALB 名称 = Albania 人口数 = 3072478
代码 = DZA 名称 = Algeria 人口数 = 30534041
代码 = ASM 名称 = American Samoa 人口数 = 57995
代码 = AND 名称 = Andorra 人口数 = 65258
代码 = AGO 名称 = Angola 人口数 = 13926705
代码 = ATG 名称 = Antigua and Barbuda 人口数 = 78536
代码 = ARG 名称 = Argentina 人口数 = 36931013
代码 = ARM 名称 = Armenia 人口数 = 3076653
代码 = ABW 名称 = Aruba 人口数 = 91031

上述重点是第12行,当我们碰上含有小数点的字符串时,需先将这个字符串转成浮点数,然后再将浮点数转成整数。

24-5-2 认识pygal.maps.world的地区代码信息

前一节有关populations.json地区代码是3个英文字母,如果我们想要使用这个json数据绘制世界人口地图,需要配合pygal.maps.world模块的方法,这个模块的地区代码是2个英文字母,所以需要将populations.json地区代码转成2个英文字母。这里本节先介绍2个英文字母的信息,pygal.maps.world模块内有COUNTRIES字典,在这个字典中国码是2个英文字母,从这里我们可以列出相关地区与代码的列表。使用pygal.maps.world模块前需先安装此模块,如下所示:

 pip install pygal.maps.world

程序实例ch24_12.py:列出pygal.maps.world模块COUNTRIES字典的2个英文字母的地区代码与完整的地区名称列表。

# ch24_12.py
from pygal.maps.world import COUNTRIES

for countryCode in sorted(COUNTRIES.keys()):
    print("代码 :", countryCode, "  名称 = ", COUNTRIES[countryCode])

执行结果
在这里插入图片描述

接着笔者将讲解,输出2个字母的地区代码时,同时输出,这个程序相当于是将2个不同来源的数据作配对。

在这里插入图片描述

程序实例ch24_13.py:从populations.json取每个名称信息,然后将每一个名称放入getCountryCode( )方法中找寻相关代码,如果找到则输出相对应的代码,如果找不到则输出“名称不吻合”。

# ch24_13.py
import json
from pygal.maps.world import COUNTRIES

def getCountryCode(countryName):
    '''输入名称回传代码'''
    for dictCode, dictName in COUNTRIES.items():    # 搜寻代码字典
        if dictName == countryName:
            return dictCode                         # 如果找到则回传代码
    return None                                     # 找不到则回传None

fn = 'populations.json'
with open(fn) as fnObj:
    getDatas = json.load(fnObj)                     # 读取人口数据json档案

for getData in getDatas:
    if getData['Year'] == '2000':                   # 筛选2000年的数据
        countryName = getData['Country Name']      
        countryCode = getCountryCode(countryName)
        population = int(float(getData['Numbers']))        
        if countryCode != None:
            print(countryCode, ":", population)     # 名称相符
        else:
            print(countryName," 名称不吻合:")       # 名称不吻合

执行结果

在这里插入图片描述

上述会有不吻合输出是因为这是2个不同单位的数据,例如,Arab World在populations.json是一个记录,在pygal.maps.world模块的COUNTRIES字典中没有这个记录。至于有关上述的更深层应用,将在下一节解说。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值