Python Json模块完全总结

Posted 嵌入式软件实战派

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python Json模块完全总结相关的知识,希望对你有一定的参考价值。

前言

JSON (JavaScript Object Notation),由 RFC 7159 (which obsoletes RFC 4627) 和 ECMA-404 指定,是一个受 JavaScript 的对象字面量语法启发的轻量级数据交换格式。

在Python中,常用的JSON模块相关API就4个:loadloadsdumpdumps

其中,使用loadloads时,相当于将下表内容反序列化成Python数据类型。

JSONPython
objectdict
arraylist
stringstr
number (int)int
number (real)float
trueTrue
falseFalse
nullNone

而使用dumpdumps时,相当于将下表内容序列化成JSON数据类型。

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int 和 float等number
Truetrue
Falsefalse
Nonenull

以下通过几个简单案例来理解这几个API的功能和用法。

load和loads

load就是从文件load一个json格式的内容,然后转换成Python类型的内容,用法很简单

with open('test.json', 'r') as f:
    js = json.load(f)
    print(type(js))
    print(js)

输出:

<class 'dict'>
{'LiLei': [98, 80, 88], 'HanMeiMei': [100, 90, 80]}

loads干嘛的呢?

d1 = '{"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}'
js1 = json.loads(d1)
print(type(js1))
print(js1)

输出:

<class 'dict'>
{'LiLei': [98, 80, 88], 'HanMeiMei': [100, 90, 80]}

从上面两个例子可以看出loadloads的区别,即load针对的是文件处理,而loads的针对的是字符串的处理。实际上,除了字符串,load还支持StringIO类型,loads还支持对bytesbytearray

from io import StringIO
io = StringIO('["streaming API"]')
json.load(io)
d1 = b'{"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}'
js1 = json.loads(d1)

其实这两个函数的区别,可以参考其参数(详见最后一小节的函数描述)

另外,有个奇怪的现象,看下面例子

d1 = "{'LiLei': [98, 80, 88], 'HanMeiMei': [100, 90, 80]}"
js1 = json.loads(d1)
print(type(js1))
print(js1)

提示错误

JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

可以理解为:只能单引号包含双引号('"abc"123'),而双引号包含单引号("'ABC'123")就不认了。

除此之外,还可以识别特殊对象,例如复数。

import json
def as_complex(dct):
	if '__complex__' in dct:
		return complex(dct['real'], dct['imag'])
	return dct
json.loads('{"__complex__": true, "real": 1, "imag": 2}', object_hook=as_complex) # (1+2j)
import decimal
json.loads('1.1', parse_float=decimal.Decimal) # Decimal('1.1')

dump和dumps

dumpdumpsload``loads是相对应的,直接看例子

with open('test2.json', 'w') as f:
    js = json.dump({"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]},f)

输出的文件内容为:

{"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}

dump函数有几个参数,separators和indent

with open('test2.json', 'w') as f:
    js = json.dump({"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]},f, separators=(',', ':'),indent = 4)
{
    "LiLei": [
        98,
        80,
        88
    ],
    "HanMeiMei": [
        100,
        90,
        80
    ]
}

实际上这个separators参数默认是separators=(',', ':'),不管它也是可以的。

同样地,dumps函数时针对具体的Python类型内容,而不是文件

d6 = {"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}
js6 = json.dumps(d6)
print(type(js6))
print(js6)
<class 'str'>
{"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}

对于特殊JSON对象

import json
class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, complex):
            return [obj.real, obj.imag]
        # Let the base class default method raise the TypeError
        return json.JSONEncoder.default(self, obj)
json.dumps(2 + 1j, cls=ComplexEncoder) # '[2.0, 1.0]'

其他更详细的参数使用,请见下面章节

函数参数说明

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*)

使用这个 转换表 将 obj 序列化为 JSON 格式化流形式的 fp (支持 .write()file-like object)。

如果 skipkeys 是 true (默认为 False),那么那些不是基本对象(包括 str, intfloatboolNone)的字典的键会被跳过;否则引发一个 TypeError

json 模块始终产生 str 对象而非 bytes 对象。因此,fp.write() 必须支持 str 输入。如果 ensure_ascii 是 true (即默认值),输出保证将所有输入的非 ASCII 字符转义。

如果 ensure_ascii 是 false,这些字符会原样输出。如果 check_circular 是为假值 (默认为 True),那么容器类型的循环引用检验会被跳过并且循环引用会引发一个 OverflowError (或者更糟的情况)。

如果 allow_nan 是 false(默认为 True),那么在对严格 JSON 规格范围外的 float 类型值(naninf-inf)进行序列化时会引发一个 ValueError

如果 allow_nan 是 true,则使用它们的 javascript 等价形式(NaNInfinity-Infinity)。

如果 indent 是一个非负整数或者字符串,那么 JSON 数组元素和对象成员会被美化输出为该值指定的缩进等级。 如果缩进等级为零、负数或者 "",则只会添加换行符。 None (默认值) 选择最紧凑的表达。 使用一个正整数会让每一层缩进同样数量的空格。 如果 indent 是一个字符串 (比如 "\\t"),那个字符串会被用于缩进每一层。

在 3.2 版更改: 允许使用字符串作为 indent 而不再仅仅是整数。

当指定时,separators 应当是一个 (item_separator, key_separator) 元组。当 indentNone 时,默认值取 (', ', ': '),否则取 (',', ': ')。为了得到最紧凑的 JSON 表达式,你应该指定其为 (',', ':') 以消除空白字符。

在 3.4 版更改: 现当 indent 不是 None 时,采用 (',', ': ') 作为默认值。

default 被指定时,其应该是一个函数,每当某个对象无法被序列化时它会被调用。它应该返回该对象的一个可以被 JSON 编码的版本或者引发一个 TypeError。如果没有被指定,则会直接引发 TypeError

如果 sort_keys 是 true(默认为 False),那么字典的输出会以键的顺序排序。

为了使用一个自定义的 JSONEncoder 子类(比如:覆盖了 default() 方法来序列化额外的类型), 通过 cls 关键字参数来指定;否则将使用 JSONEncoder

在 3.6 版更改: 所有的可选参数现在是 keyword-only 的了。

注解:picklemarshal 不同,JSON 不是一个具有框架的协议,所以尝试多次使用同一个 fp 调用 dump()来序列化多个对象会产生一个不合规的 JSON 文件。

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

使用这个 转换表obj 序列化为 JSON 格式的 str。 其参数的含义与 dump()中的相同。

注解: JSON 中的键-值对中的键永远是 str 类型的。当一个对象被转化为 JSON 时,字典中所有的键都会被强制转换为字符串。这所造成的结果是字典被转换为 JSON 然后转换回字典时可能和原来的不相等。换句话说,如果 x 具有非字符串的键,则有 loads(dumps(x)) != x

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

使用这个 转换表将 fp (一个支持 .read() 并包含一个 JSON 文档的 text file 或者 binary file) 反序列化为一个 Python 对象。

object_hook 是一个可选的函数,它会被调用于每一个解码出的对象字面量(即一个 dict)。object_hook 的返回值会取代原本的 dict。这一特性能够被用于实现自定义解码器(如 JSON-RPC 的类型提示)。

object_pairs_hook 是一个可选的函数,它会被调用于每一个有序列表对解码出的对象字面量。 object_pairs_hook 的返回值将会取代原本的 dict 。这一特性能够被用于实现自定义解码器。如果 object_hook 也被定义, object_pairs_hook 优先。

在 3.1 版更改: 添加了对 object_pairs_hook 的支持。

parse_float ,如果指定,将与每个要解码 JSON 浮点数的字符串一同调用。默认状态下,相当于 float(num_str) 。可以用于对 JSON 浮点数使用其它数据类型和语法分析程序 (比如 decimal.Decimal )。

parse_int ,如果指定,将与每个要解码 JSON 整数的字符串一同调用。默认状态下,相当于 int(num_str) 。可以用于对 JSON 整数使用其它数据类型和语法分析程序 (比如 float )。

parse_constant ,如果指定,将要与以下字符串中的一个一同调用: '-Infinity''Infinity''NaN' 。如果遇到无效的 JSON 数字则可以使用它引发异常。

在 3.1 版更改: parse_constant 不再调用 ‘null’ , ‘true’ , ‘false’ 。

要使用自定义的 JSONDecoder 子类,用 cls 指定他;否则使用 JSONDecoder 。额外的关键词参数会通过类的构造函数传递。

如果反序列化的数据不是有效 JSON 文档,引发 JSONDecodeError 错误。

在 3.6 版更改: 所有的可选参数现在是 keyword-only 的了。

在 3.6 版更改: fp 现在可以是 binary file 。输入编码应当是 UTF-8 , UTF-16 或者 UTF-32 。

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

使用这个 转换表将 s (一个包含 JSON 文档的 str, bytesbytearray 实例) 反序列化为 Python 对象。

其他参数的含义与 load()中的相同。

如果反序列化的数据不是有效 JSON 文档,引发 JSONDecodeError 错误。

在 3.6 版更改: s 现在可以为 bytesbytearray 类型。 输入编码应为 UTF-8, UTF-16 或 UTF-32。

在 3.9 版更改: 关键字参数 encoding 已被移除。

以上是关于Python Json模块完全总结的主要内容,如果未能解决你的问题,请参考以下文章

json模块使用总结——Python

python基础总结

Python课程学习总结

json模块

python json模块

python 模块-json