引言

你一定听说过 JSON 吧。JSON 是当前最常用的数据传输格式之一,纯文本,容易使用,方便阅读,最重要的是在多个场合都被大量被使用。

既然 JSON 这么好,那就让我们继续探险,去掌握 python 中对 JSON 的常用操作吧, okay, let's go!

基础知识

庄子曰:“水之积也不厚,则其负大舟也无力。”。要完全掌握一个知识点,先将这个知识点需要的基础知识补齐,这样学的才能牢固。

下面就是我认为学习对 JSON 操作前的知识点。如果您对这部分已经了然于胸,尽可以略过这部分,跳到下一节。

什么是 JSON?

Json (Javascript Object Notation) 是一种轻量级的数据交换格式,它基于 Javascript 的对象字面量。尽管它只是 Javascript 的一个子集,但它与语言无关。以现代编程语言编写的程序,都可以用它来彼此交换数据。它是一种文本格式,人和机器都可以阅读它。

—— 《Javascript 语言精粹》

既然以现代编程语言都可以用它来交换数据,强大的 python 当然也不例外。要更好的使用 JSON 一定要先了解下它的语法。

JSON 的语法

JSON 的值分为 6 种类型,分别是对象,数组,字符串,数字,布尔值 (truefalse )和null。来看一个典型的 JSON 集合,体会下这些类型。

{
"obj": {
"name": "xxx",
"address": {
"country": "china",
"city": "TianJin"
}
},
"arr_simple": [1, 2, 3, 5],
"arr_complex": [
1,
"a",
{
"b": "yyy"
},
true,
null
],
"str": "I am a string",
"num": 888,
"booValue": false,
"nullValue": null
}

看上面代码, JSON 语法有什么特点呢?

  1. JSON 字符串必须使用 双引号包围
  2. 可以在任何值前后插入空白(包括空格,制表符,回车,换行),当然这些空白符也可以去除。

像字符串,数字,布尔值,null 都比较简单,无需细数,接下来我们重点来看下对象和数组。

JSON 对象有哪些特点?

JSON 对象的结构是什么样子呢?

上面代码中的 obj 就是一个 JSON 对象,我们来观察下它。

  1. 它是用 {} 括起来的一个集合,每一项都包含名称 ,如 name 就是名称,而值就是 xxx
  2. 名称可以是任意字符串,但必须是字符串才可以哦。
  3. 值只要是上面 6 种类型之一就可以
  4. 名称/值 对没有固定的顺序,可以是任意顺序
  5. 可以支持无限层的嵌套,如 obj 对象中嵌套了一个 address 对象,但是为了保证处理的高效性,请尽量保持结构的扁平性,也就是不要嵌套太多层哦)

为了能够处理 JSON 数据,许多语言都有对应的数据类型可以映射为 JSON 对象,那么 python 中是什么数据类型呢?

dict ,如果有您对 dict 有些遗忘了,就请到这里复习下吧。

JSON 数组有哪些特点?

上面代码中的 arr_simplearr_complex 都表示数组,它们有哪些特点呢?

  • 是一个 有序序列
  • 只有 组成
  • 值可以是任意类型的 JSON 值,如 arr_complex 数组。

python 也有能够映射为 JSON 对象的数据类型,是 listtuple , 如果您对 listtuple 的特性有些生疏了,也可以在这里回顾下。

什么是编码和解码?

说到 JSON 和 python 之间的转换,就会涉及到两个名词:编码解码

那么到底什么是编码和解码呢?

编码信息从一种形式格式转换为另一种形式的过程。解码,是编码的逆过程,亦即把编码过的信息恢复成原来样式。

——维基百科

编码的作用则是为了利于传输和存储,JSON 当然是非常适合的。因此,

  • 把 python 对象转换成 JSON 的过程就称为编码
  • 把 JSON 转换成 python 对象的过程就称为解码

常用的 json 操作有哪些?

刚开始接触 json 的操作,我主要有下面几个疑问:

  • json 操作需要什么库?
  • 如何将 python 对象转换成 JSON字符串,更进一步,能不能直接转换成文件句柄存储到文件中?(编码)
  • 如何将 json 字符串转换成 python 对象,更进一步,能不能直接将 JSON 格式的文件转换成 python 对象?(解码)

下面就让我们一一来探索这些问题。

json 操作需要什么库?

使用 json 函数前需要先导入 json 库:

import json

json 库本身就是 python 内置的标准库,因此你不需要做任何安装的操作。只要声明了上面语句,就可直接使用。

如何将 python 编码成 JSON?

python 编码为 JSON 的对照表

要完成这个功能,先要看下 python 数据结构编码为 json 的对照表。

Python JSON
dict object
list, tuple array
str string
int, float, int- & float-derived Enums number
True true
False false
None null

有了这张表,我们就可以清楚的知道 python 对象将编码成的 json 格式。

json.dumps()

json.dumps() 方法的作用就是将 python 对象转换成 JSON 字符串,下面来看具体的函数声明:

json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)

参数看起来好多啊,不过不用担心,这么多参数,只有第一个参数是必填的。下面就来一一了解下这些参数的意义

  • obj 就是要编码的 python 对象
  • skipkeys 默认值是 False。设置为 True ,假如 obj 中的 dict keys 不是基本类型(str , int , float , bool , None ), 就会被忽略,而不是抛出 TypeError 错误
  • ensure_ascii 默认是 True , 表示默认使用ascii 编码。如果 obj 内含有非 ASCII 字符,就会出现 "\uXXXX" 格式显式的数据, 设置成 False 就会使用字符本来的编码。
    • 这里要注意,如果输入是中文,需要指定 ensure_ascii=False
  • check_circular 默认值是 True,如果设置为 False 就不会检查内部类型是否包含循环引用,而且循环引用会导致 OverflowError
  • allow_nan 默认值为 False ,如果碰到超过范围的 float 值(nan, inf, -inf )就使用 (NaN,Infinity, -Infinity) 替换
    • 如果为 True 碰到这些值则会导致 ValueError
  • indent 缩进设置
    • 如果是非负整数或者 string, JSON Array 元素和对象元素将会按照设置的缩进格式化显示
    • 值为 0, 负值,或者 "" 只会插入新的一行
    • 值为 None (也是默认值)会尽可能的压缩
  • separators 分隔符。
    • 如果要设置它,参数需要是一个元组(item_separator, key_separator)
    • 默认值是 (', ', ': ') ,表示 keys 之间用 , 隔开,而 key 和 value 之间用 : 隔开
  • sort_keys 默认值是 False ,如果设置成 True , dict 结构的输出就会按照 key 来排序
  • encoding 默认值是 UTF-8 用于设置 JSON 数据的编码方式,在处理中文时这里一定要注意。

来看一个例子

>>> import json
>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> print(json.dumps("\"foo\bar"))
"\"foo\bar"
>>> print(json.dumps('\u1234'))
"\u1234"
>>> print(json.dumps('\\'))
"\\"
>>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
{"a": 0, "b": 0, "c": 0}

json.dump()

json.dump() 函数的作用就是将 python 对象转换成 JSON 字符串,并将其通过 fp 文件流写入到文件中。来看下具体的函数声明:

 json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

和前面的 dumps 函数进行比较,会发现两个函数的参数是非常相似的,而且它们的意义也都相同。来看下面的例子

>>> import json
>>> from io import StringIO
>>> io = StringIO()
>>> json.dump(['streaming API'], io)
>>> io.getvalue()
'["streaming API"]'

如何将 JSON 解码成 python 对象?

JSON 解码为 python 的对照表

要完成这个功能,也先要看下 json 解码为 python 对象的对照表

JSON Python
object dict
array list
string str
number (int) int
number (real) float
true True
false False
null None

编码对照表和解码对照表并不是一一对应的,因此如果一个 python对象 先编码成 JSON,再转码回来后得到的对象可就不一定完全相等了。

json.loads()

这个方法的作用就是将参数 s 按照上面的对照表反序列化为一个 python 对象。参数 s 可以是 str ,byte 或者byteArray 格式, 但必须要包含 JSON 文本才可以)。具体函数声明如下:

json.loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

下面就来一一了解下一些常用参数的意义

  • s 就是要解码的 python 字符串
  • encoding 指定编码格式
  • parse_float ,默认情况下相当于 float(num_str)。如果设置为其他值,将会把一个 JSON 字符串按照 float 解码调用,
  • parse_int ,默认情况下相当于 int(num_str),如果指定,将把每个 JSON 字符串按照 int 解码调用

来看下面的例子,其中最后一行就指定了 parse_float

>>> import json
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')
'"foo\x08ar'
>>> import decimal
>>> json.loads('1.1', parse_float=decimal.Decimal)
Decimal('1.1')

json.load()

先来看函数声明

 json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

作用是将 fp 文件流反序列化为 python 对象,其中的参数意义和 loads 方法相同。来看一个例子。

>>> import json
>>> from io import StringIO
>>> io = StringIO('["streaming API"]')
>>> json.load(io)
['streaming API']

结语

本文主要介绍了 JSON 的定义,语法以及 JSON 的常用操作。但是并没有涉及 JSON 处理自定义数据类型的高级内容(JSONEncoderJSONDecoder),这部分内容会再后面的篇章中专门介绍。

下篇会介绍 python 的模块,敬请期待。

参考文档

  1. python json API Library
  2. 《Javascript 语言精粹》
  3. 编码—维基百科

相关文章列表

python 历险记(四)— python 中常用的 json 操作的更多相关文章

  1. 【转】python 历险记(四)— python 中常用的 json 操作

    [转]python 历险记(四)— python 中常用的 json 操作 目录 引言 基础知识 什么是 JSON? JSON 的语法 JSON 对象有哪些特点? JSON 数组有哪些特点? 什么是编 ...

  2. LoadRunner中常用的字符串操作函数

    LoadRunner中常用的字符串操作函数有:                strcpy(destination_string, source_string);               strc ...

  3. python中常用的时间操作

    python中常用的时间模块有time和datetime,以下是这两个模块中常用的方法: #先引入模块 import timefrom datetime import datetiem, timezo ...

  4. 【python正则】工作中常用的python正则代码

    工作中常用的一些正则代码: 01.用户名正则 import re # 4到16位(字母,数字,下划线,减号)if re.match(r'^[a-zA-Z0-9_-]{4,16}$', "ab ...

  5. 工作中常用的QTP操作Excel函数

    前言 本文只是对工作中常用的EOM相关函数的整理,并不是要写个大而全的操作手册,如果想对EOM有更多的了解可以参考QTP的帮助文档或查看QTP安装目录\CodeSamplesPlus\UsingExc ...

  6. 工作中常用的Git操作

    粘贴自:微信公众号:程序员共成长 分支操作: git branch 创建分支 git branch -b 创建并切换到新建的分支上 git checkout 切换分支 git branch 查看分支列 ...

  7. Python requests.post方法中data与json参数区别

    在通过requests.post()进行POST请求时,传入报文的参数有两个,一个是data,一个是json. data与json既可以是str类型,也可以是dict类型. 区别: 1.不管json是 ...

  8. Python Requests post方法中data与json参数问题

    1.data参数 你想要发送一些编码为表单形式的数据——非常像一个 HTML 表单.要实现这个,只需简单地传递一个字典给 data 参数.你的数据字典在发出请求时会自动编码为表单形式,header默认 ...

  9. Python学习(四) Python数据类型:序列(重要)

    插播一下,先了解一下Python的数据类型,Python现有的数据类型有好多,最重要的有列表.元组.字典 列表:我觉得可以对应java中的数组 list=['physics', 'chemistry' ...

随机推荐

  1. debian 系统安装配置apache

    安装sshapt-get install ssh-server  (安装失败请插入镜像)service ssh start Apache 服务安装apt-get install apache2 apa ...

  2. bzoj1001狼抓兔子

    1001: [BeiJing2006]狼抓兔子 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你 ...

  3. 自学Linux Shell11.2-echo命令

    点击返回 自学Linux命令行与Shell脚本之路 11.2-echo命令 echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用. 语 法:echo [-n][字符串]或 echo [- ...

  4. Canvas与javaScript特效笔记

    第六章   Canvas与javaScript特效笔记 q  <canvas>标签的用途 HTML5 canvas 提供了通过 JavaScript 绘制图形的方法,此方法使用简单但功能强 ...

  5. emwin 之变量定义位置

    @2018-08-13 小记 本意是想在回调函数中定义一变量暂存下拉框操作前的的设定值,与后期更改的设定值作比较后更新操作,但结果失败了 分析后,此变量定义为局部变量,emwin回调函数又是事件触发型 ...

  6. FreeRTOS不允许在中断服务程序和临界段中执行不确定的性的操作

    举例 等待事件标志组的任务,要是在中断服务程序中设置事件标志组,但不知道当前有多少个任务在等待此事件标志,这个操作即为不确定性操作,为了不在中断服务程序中执行此不确定性操作,只在中断服务程序中给一确定 ...

  7. 单片机如何产生PWM信号

    用89C52产生控制二相步进电机的程序,用PWM信号控制步进电机 用普通I/O口采用软件定时器中断可以模拟PWM输出 /*采用6MHz晶振,在P1.0脚上输出周期为2.5s,占空比为20%的脉冲信号* ...

  8. 手动实现property装饰器

    首先,property装饰器是通过数据描述符实现的.用法很简单,大家应该都知道,这里就不细说了. 这里主要分析一下property是如何通过描述符实现的. class Property: def __ ...

  9. 【CH1602】最大异或和 trie+贪心

    题目大意:给定 N 个数,求这 N 个数中任选两个数进行异或运算,求最大的异或和是多少. 一个 int 类型的整数,可以看作一个长度为32位的字符串,异或运算不像加法,最大值不一定是由两个较大值得到. ...

  10. CodeForces892E 可撤销并查集/最小生成树

    http://codeforces.com/problemset/problem/892/E 题意:给出一个 n 个点 m 条边的无向图,每条边有边权,共 Q 次询问,每次给出 ki​ 条边,问这些边 ...