JSON(JavaScript Object Notation)是由道格拉斯·克罗克福特构想和设计的一种轻量级资料交换格式。其内容由属性和值所组成,因此也有易于阅读和处理的优势。JSON是独立于编程语言的资料格式,其不仅是JavaScript的子集,也采用了C语言家族的习惯用法,目前也有许多编程语言都能够将其解析和字符串化,其广泛使用的程度也使其成为通用的资料格式。
Python 的 json
库提供了对 json
序列化的支持,与标准库 marshal
和 pickle
相似的API接口。
在看下列内容前,别忘记导入 json 标准库呀
import json
1)、JSON 到 Python 数据类型的转换
JSON 数据格式 | To Python 数据格式 |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
2)、Python 到 JSON 数据类型的转换
Python 数据格式 | To JSON 数据格式 |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int 和 float 派生的枚举 | number |
True | true |
False | false |
None | null |
3)、源码查阅
在 JSON 标准库的编码器和解码器源码里,能看到对转换类型的注释
JSONEncoder
class JSONEncoder(object):
"""Extensible JSON encoder for Python data structures.
Supports the following objects and types by default:
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
To extend this to recognize other objects, subclass and implement a
``.default()`` method with another method that returns a serializable
object for ``o`` if possible, otherwise it should call the superclass
implementation (to raise ``TypeError``).
"""
pass
JSONDecoder
class JSONDecoder(object):
"""Simple JSON decoder
Performs the following translations in decoding by default:
+---------------+-------------------+
| JSON | Python |
+===============+===================+
| object | dict |
+---------------+-------------------+
| array | list |
+---------------+-------------------+
| string | str |
+---------------+-------------------+
| number (int) | int |
+---------------+-------------------+
| number (real) | float |
+---------------+-------------------+
| true | True |
+---------------+-------------------+
| false | False |
+---------------+-------------------+
| null | None |
+---------------+-------------------+
It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
their corresponding ``float`` values, which is outside the JSON spec.
"""
pass
1)、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
格式化流形式并存储到 文件,需要注意的是 json 模块始终返回的是 str
字符串对象,因此在将 JSON 读写文件时应以文本模式操作,在序列化操作时应确保 fp.write
支持 str
写入。
参数如下:
.write()
写入方法的文件对象,比如 file-like
object,需要注意的是应传入一个文本模式的文件对象,并且编码应当是 UTF-8 , UTF-16 或者 UTF-32 。True
时(默认为 False
)跳过不是基本对象(包括 str
, int
、float
、bool
、None
)字典的键,否则引发一个 TypeError
异常。True
时(默认为 True
),输出保证将所有输入的非 ASCII 字符转义。如果 ensure_ascii 是 false,这些字符会原样输出。False
(默认为 True
),那么容器类型的循环引用检验会被跳过并且循环引用回引发一个 OverflowError
(或者更糟的情况)。False
(默认为 True
),那么在对严格 JSON
规格范围外的 float
类型值(nan
、inf
和 -inf
)进行序列化时会引发一个 ValueError
异常。如果为 True
,则使用它们的 JavaScript 等价形式(NaN
、Infinity
和 -Infinity
)。JSONEncoder
。如果想使用自定义的 JSON 编码器,比如说 JSONEncoder
子类,通过此参数实现。None
会选择最紧凑的表达,即一行数据。""
,则只会添加换行符,在每个缩进前都不会有字符。(item_separator, key_separator)
元组(项分割字符,键分割字符)。indent
的存在,separators
的默认值会有两种变化,当 indent
为 None
时,会使用紧凑的一行表达,这时候的分割符会取值 (', ', ': ')
在每个分割符后都有空格,而相反在不为 None
时会取值 (',', ':')
。None
的情况下,可以手动将 separators 取值为 (',', ':')
,也就是不留空格。TypeError
。如果没有被指定,则会直接引发 TypeError
。True
(默认为 False),那么字典的输出会以键的顺序排序。具体讲解:
取消非ASCII编码转义
在将 JSON 编码的数据存储到文件或是进行编码返回时,很容易发现除了ASCII字符都发生了转义,变成了Unicode的转义字符,最典型的例子就是中文字符。
# -*- coding: utf-8 -*-
import json
from pathlib import Path
BASE_DIR = Path(__file__).parent
happly_new_year = {
"年份": 2022, "生肖": "虎",
"祝福语": "在这美丽的春节之际,祝福各位朋友在新的一年里,天天都有份好心情!",
"春节快乐": None
}
# 文件路径
file_path = BASE_DIR / "test.json"
# 打印输出到控制台
print(json.dumps(happly_new_year))
# 输出存储到文件
with file_path.open("w", encoding="utf-8") as f_w:
json.dump(happly_new_year, fp=f_w)
控制台输出 与 输出到文件
{"\u5e74\u4efd": 2022, "\u751f\u8096": "\u864e", "\u795d\u798f\u8bed": "\u5728\u8fd9\u7f8e\u4e3d\u7684\u6625\u8282\u4e4b\u9645\uff0c\u795d\u798f\u5404\u4f4d\u670b\u53cb\u5728\u65b0\u7684\u4e00\u5e74\u91cc\uff0c\u5929\u5929\u90fd\u6709\u4efd\u597d\u5fc3\u60c5!", "\u6625\u8282\u5feb\u4e50": null}
那么对其进行 JSON 编码时如何取消发生的非 ASCII 字符转义,让这些字符会原样输出呢?答案很简单,在每次编码时将 ensure_ascii
参数设置为 Flase
即可。
上部分的代码保持不变,只是添加ensure_ascii
参数
......
# 打印输出到控制台
print(json.dumps(happly_new_year, ensure_ascii=False))
# 输出存储到文件
with file_path.open("w", encoding="utf-8") as f_w:
json.dump(happly_new_year, fp=f_w, ensure_ascii=False)
控制台输出 与 输出到文件
{"年份": 2022, "生肖": "虎", "祝福语": "在这美丽的春节之际,祝福各位朋友在新的一年里,天天都有份好心情!", "春节快乐": null}
JSON 数据格式化
每次输出的 JSON 数据都是一行显示的,在数据量比较少的情况下还能阅读,当数据量一旦多起来后阅读体验上就没那么好了。JSON 本身就是一种注重数据结构化的格式,在维护调试时可以充分发挥其优点,对其进行格式化就是一种常见手段。
将其进行格式化返回需要使用到 indent
参数,indent
参数的作用在参数讲解部分有将,这边咱们对这个参数作用进行展示。
以四个空格为缩进
# -*- coding: utf-8 -*-
import json
from pathlib import Path
BASE_DIR = Path(__file__).parent
happly_new_year = {
"年份": 2022, "生肖": "虎",
"祝福语": "在这美丽的春节之际,祝福各位朋友在新的一年里,天天都有份好心情!",
"春节快乐": None
}
# 文件路径
file_path = BASE_DIR / "test.json"
# 打印输出到控制台
print(json.dumps(happly_new_year, indent=4, ensure_ascii=False))
# 输出存储到文件
with file_path.open("w", encoding="utf-8") as f_w:
json.dump(happly_new_year, fp=f_w, indent=4, ensure_ascii=False)
{
"年份": 2022,
"生肖": "虎",
"祝福语": "在这美丽的春节之际,祝福各位朋友在新的一年里,天天都有份好心情!",
"春节快乐": null
}
以两个空格为缩进
......
# 打印输出到控制台
print(json.dumps(happly_new_year, indent=2, ensure_ascii=False))
# 输出存储到文件
with file_path.open("w", encoding="utf-8") as f_w:
json.dump(happly_new_year, fp=f_w, indent=2, ensure_ascii=False)
{
"年份": 2022,
"生肖": "虎",
"祝福语": "在这美丽的春节之际,祝福各位朋友在新的一年里,天天都有份好心情!",
"春节快乐": null
}
default 参数的妙用
default 其实是一个很方便的参数,向这个参数传入一个处理自定义对象的函数,就能够将这些自定义对象转义成可以被 JSON 编码的版本,而不需要在将数据序列化前还要手动转义 JSON 编码器无法解析的数据源。
有一个水果类,为每一种水果都新建一个对象,每个对象中都有一个方法可以将其转义成可以被 JSON 编码版本的方法,需要做的是在每次序列化时都能正确调用这个方法将其转义。这时 default 这个参数就派上用场了,传入 default 的函数要做两件事,如果是水果类的对象那就将其转义,如果不是则抛出异常。
# -*- coding: utf-8 -*-
import json
from pathlib import Path
BASE_DIR = Path(__file__).parent
class Fruits:
"""水果类"""
def __init__(self, name, price):
self.name = name
self.price = price
def __str__(self):
return f"水果类型:{self.name},售价:{self.price}"
def todict(self):
"""将水果信息转换成字典格式输出"""
return {"水果": self.name, "售价": self.price}
def obj_to_json(obj):
"""对象转为JSON能编码函数
Args:
obj: 自定义对象
Returns:
能够被JSON编码的版本数据
Raises:
如果不是目标类别的对象将抛出TypeError异常
"""
if isinstance(obj, Fruits):
return obj.todict()
raise TypeError(f"Object of type {obj.__name__} is not JSON serializable")
pear = Fruits("梨子", 3.3)
apple = Fruits("苹果", 5.6)
banana = Fruits("香蕉", 11.6)
orange = Fruits("橙子", 6.6)
fruits = [pear, apple, banana, orange]
# 文件路径
file_path = BASE_DIR / "test.json"
with file_path.open("w", encoding="utf-8") as f_w:
json.dump(fruits, fp=f_w, default=obj_to_json, ensure_ascii=False)
JSON 数据
[{"水果": "梨子", "售价": 3.3}, {"水果": "苹果", "售价": 5.6}, {"水果": "香蕉", "售价": 11.6}, {"水果": "橙子", "售价": 6.6}]
2)、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
对象并返回,不会进行文件式存储
除了缺少用于存储到文件的 fp
参数外,其它参数的含义与 json.dump()
中的相同,因此用法也是一样的,只不过一个是存储到文件,一个是直接返回 JSON 编码数据,这里不过多讲解
注解: JSON 中的键-值对中的键永远是 str 类型的。当一个对象被转化为 JSON 时,字典中所有的键都会被强制转换为字符串。这所造成的结果是字典被转换为 JSON 然后转换回字典时可能和原来的不相等。换句话说,如果 x 具有非字符串的键,则有 loads(dumps(x)) != x。比如说在Python数据类型中以整数为键,转化为 JSON 时这些整数将会变成字符串类型。
1)、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 对象。
参数如下:
.read()
写入方法的文件对象,该文件对象应是 text file
(文本对象)或 binary file
(二进制对象),对于二进制对象输入编码应当是 UTF-8 , UTF-16 或者 UTF-32。dict
、一个基本类型对象),此函数接受一个参数,这个参数就是每一个解码出的对象字面量。dict
,简单来说就是该函数负责把反序列化后的基本类型对象转换成自定义类型的对象。这一特性能够被用于实现自定义解码器(如 JSON-RPC 的类型提示)。float(num_str)
。decimal.Decimal
)。int(num_str)
。float
)。'-Infinity'
, 'Infinity'
, 'NaN'
。其应该是一个函数,同时接收一个参数,这个参数是每一个 JSON 整数的字符串。如果遇到无效的 JSON 数字则可以使用它引发异常。object_hook
参数功能相同,与 object_hook
参数不同点是给 object_pairs_hook
的解码的键值对列表是有序的,一些依赖键值对顺序的功能可以用 object_pairs_hook
参数,而不用 object_hook
。object_hook
也被定义,object_pairs_hook
优先。具体讲解:
JSON 浮点数处理
parse_float
参数用于控制 JSON 浮点数转化为 Python 数据类型时的操作,默认是对其转化为浮点数类型 float(num_str)
,浮点数还能做的处理,比如四舍五入,向上向下取整,转化为decimal.Decimal
等,这些都能直接靠 parse_float
参数实现。
# -*- coding: utf-8 -*-
import math
import json
from pathlib import Path
from decimal import Decimal
BASE_DIR = Path(__file__).parent
# 文件路径
file_path = BASE_DIR / "test.json"
def json_ceil(dic):
"""将json浮点数向上取整辅助函数"""
return math.ceil(float(dic))
def json_floor(dic):
"""将json浮点数向下取整辅助函数"""
return math.floor(float(dic))
def json_round(dic):
"""将json浮点数四舍五入取整辅助函数"""
return round(float(dic))
def float_to_decimal(dic):
"""将json浮点数转化Decimal辅助函数"""
return Decimal.from_float(float(dic))
.......
源 JSON 数据
[{"水果": "梨子", "售价": 3.3}, {"水果": "苹果", "售价": 5.6}, {"水果": "香蕉", "售价": 11.6}, {"水果": "橙子", "售价": 6.6}]
向上取整
......
with file_path.open("r", encoding="utf-8") as f_r:
print(json.load(f_r, parse_float=json_ceil))
[{'水果': '梨子', '售价': 4}, {'水果': '苹果', '售价': 6}, {'水果': '香蕉', '售价': 12}, {'水果': '橙子', '售价': 7}]
向下取整
......
with file_path.open("r", encoding="utf-8") as f_r:
print(json.load(f_r, parse_float=json_floor))
[{'水果': '梨子', '售价': 3}, {'水果': '苹果', '售价': 5}, {'水果': '香蕉', '售价': 11}, {'水果': '橙子', '售价': 6}]
四舍五入取整
......
with file_path.open("r", encoding="utf-8") as f_r:
print(json.load(f_r, parse_float=json_round))
[{'水果': '梨子', '售价': 3}, {'水果': '苹果', '售价': 6}, {'水果': '香蕉', '售价': 12}, {'水果': '橙子', '售价': 7}]
转化为Decimal类型
......
with file_path.open("r", encoding="utf-8") as f_r:
print(json.load(f_r, parse_float=float_to_decimal))
[{'水果': '梨子', '售价': Decimal('3.29999999999999982236431605997495353221893310546875')}, {'水果': '苹果', '售价': Decimal('5.5999999999999996447286321199499070644378662109375')}, {'水果': '香蕉', '售价': Decimal('11.5999999999999996447286321199499070644378662109375')}, {'水果': '橙子', '售价': Decimal('6.5999999999999996447286321199499070644378662109375')}]
JSON 整数处理
在解析 JSON 整数字符串时,默认是将其转化为整数类型 int(num_str)
,可以将其转化为浮点数类型,直接靠 parse_float
参数实现。
# -*- coding: utf-8 -*-
import math
import json
from pathlib import Path
from decimal import Decimal
BASE_DIR = Path(__file__).parent
file_path = BASE_DIR / "test.json"
with file_path.open("r", encoding="utf-8") as f_r:
print(json.load(f_r, parse_int=float))
源 JSON 数据
{"祝福语": "新春快乐!", "祝你": 1314}
程序打印
{'祝福语': '新春快乐!', '祝你': 1314.0}
object_hook 与 object_pairs_hook 的应用
object_hook
参数与 object_pairs_hook
参数功能都是一致的,但在编写函数时,函数接受的参数不同。对于 object_hook
参数,传入的是每一个解码出来最基本的类型对象,即每次传入都是 dict
字典数据类型。对于 object_pairs_hook
参数,传入的是每一个解码出来的列表嵌套元组类型 [(key, value), ]
,相当于调用了字典的 .items()
方法。
颁奖排序算是一个典型例子,以数字1、2、3…为颁奖奖次的依据,分别使用 object_hook
参数与 object_pairs_hook
参数进行示例。
# -*- coding: utf-8 -*-
import json
s_data = '''{
"3": ["第三名", "王汗"], "1": ["第一名", "王小明"], "2": ["第二名", "小明"],
"4": ["第四名", "李华"], "5": ["第五名", "李大川"], "6": ["第六名", "xianzhe_"]
}'''
# 使用 object_hook 参数
json.loads(s_data, object_hook=lambda x: print(f"类型:{type(x)},内容:{x}"))
# 使用 object_pairs_hook 参数
json.loads(s_data, object_pairs_hook=lambda x: print(f"类型:{type(x)},内容:{x}"))
"类型:,内容:{'3': ['第三名', '王汗'], '1': ['第一名', '王小明'], '2': ['第二名', '小明'], '4': ['第四名', '李华'], '5': ['第五名', '李大川'], '6': ['第六名', 'xianzhe_']}"
"类型:,内容:[('3', ['第三名', '王汗']), ('1', ['第一名', '王小明']), ('2', ['第二名', '小明']), ('4', ['第四名', '李华']), ('5', ['第五名', '李大川']), ('6', ['第六名', 'xianzhe_'])]"
可以看到 object_pairs_hook
并没有返回一个有序列表,而是和 object_hook
一样的顺序,我的猜测是因为程序内部并不知道排序的依据是什么,但其实 object_pairs_hook
传入的参数是列表,那么自己手动指定排序即可
根据Key键值的排序返回
# -*- coding: utf-8 -*-
import json
s_data = '''{
"3": ["第三名", "王汗"], "1": ["第一名", "王小明"], "2": ["第二名", "小明"],
"4": ["第四名", "李华"], "5": ["第五名", "李大川"], "6": ["第六名", "xianzhe_"]
}'''
def sort_hook(dic):
"""将Json解码结果排序辅助函数
如果是object_hook参数使用将直接返回
Args:
dic: 最基本的类型对象
"""
if isinstance(dic, list):
dic.sort(key=lambda i: i[0])
return dic
else:
return dic
# 使用 object_hook 参数
print(json.loads(s_data, object_hook=sort_hook))
# 使用 object_pairs_hook 参数
print(json.loads(s_data, object_pairs_hook=sort_hook))
{'3': ['第三名', '王汗'], '1': ['第一名', '王小明'], '2': ['第二名', '小明'], '4': ['第四名', '李华'], '5': ['第五名', '李大川'], '6': ['第六名', 'xianzhe_']}
[('1', ['第一名', '王小明']), ('2', ['第二名', '小明']), ('3', ['第三名', '王汗']), ('4', ['第四名', '李华']), ('5', ['第五名', '李大川']), ('6', ['第六名', 'xianzhe_'])]
两个参数同时存在的情况下,object_pairs_hook
优先级更高
# -*- coding: utf-8 -*-
import json
s_data = '''{
"3": ["第三名", "王汗"], "1": ["第一名", "王小明"], "2": ["第二名", "小明"],
"4": ["第四名", "李华"], "5": ["第五名", "李大川"], "6": ["第六名", "xianzhe_"]
}'''
def hook(dic):
if isinstance(dic, list):
return "object_pairs_hook优先"
else:
return "object_hook优先"
print(json.loads(s_data, object_hook=hook, object_pairs_hook=hook))
object_pairs_hook优先
2)、json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
将JSON 编码的 s
字符串对象反序列化为一个 Python 对象。
与 json.loads()
不同的是,不需要从一个文件对象走获取 JSON 编码数据,而是直接传入一个 JSON 编码的字符串对象,其它参数的含义与 json.loads()
中的相同,因此用法也是一样的,这里不过多讲解。
参数如下:
str
的缩写,传入需要反 JSON 序列化的字符串对象注解:如果反序列化的数据不是有效 JSON 文档,引发
JSONDecodeError
错误。
1)、class json.JSONDecoder(*, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None)
Python 实现 JSON 解码的重要组成部分,一个简单的 JSON 解码器。
在调用反序列化 json.load()
、json.loads()
方法时,传入的参数大部分实则传给了解码器,这也是参数名一致的原因。
同时将JSON 的 NaN
、Infinity
和 -Infinity
理解为 Python 对应的 float
值。
源码:
通过查看源码可以看到,JSON 的反序列化方法实则是调用了 JSONDecoder
解码器。
部分源码
......
if cls is None:
cls = JSONDecoder
if object_hook is not None:
kw['object_hook'] = object_hook
if object_pairs_hook is not None:
kw['object_pairs_hook'] = object_pairs_hook
if parse_float is not None:
kw['parse_float'] = parse_float
if parse_int is not None:
kw['parse_int'] = parse_int
if parse_constant is not None:
kw['parse_constant'] = parse_constant
return cls(**kw).decode(s)
参数如下:
解码器的参数功能大部分与反序列化 json.load()
、json.loads()
方法一致。
dict
、一个基本类型对象),此函数接受一个参数,这个参数就是每一个解码出的对象字面量。dict
,简单来说就是该函数负责把反序列化后的基本类型对象转换成自定义类型的对象。这一特性能够被用于实现自定义解码器(如 JSON-RPC 的类型提示)。float(num_str)
。int(num_str)
。'-Infinity'
, 'Infinity'
, 'NaN'
。其应该是一个函数,同时接收一个参数,这个参数是每一个 JSON 整数的字符串。如果遇到无效的 JSON 数字则可以使用它引发异常。False
(默认为 True
),那么控制字符将被允许在字符串内。在此上下文中的控制字符编码在范围 0–31 内的字符,包括 '\t'
(制表符), '\n'
,'\r'
和 '\0'
。object_hook
参数功能相同,与 object_hook
参数不同点是给 object_pairs_hook
的解码的键值对列表是有序的,一些依赖键值对顺序的功能可以用 object_pairs_hook
参数,而不用 object_hook
。object_hook
也被定义,object_pairs_hook
优先。方法功能
decode(s)
返回参数 s
的 Python 表示形式,参数 s
是包含一个 JSON 文档的字符串 str
实例。
raw_decode(s)
原始解码数据。从参数 s
中解码出 JSON 文档(以 JSON 文档开头的一个 str 对象)并返回一个 Python 表示形式为 2 元组以及指明该文档在 s 中结束位置的序号。
这可以用于从一个字符串解码JSON文档,该字符串的末尾可能有无关的数据。
2)、class json.JSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)
Python 实现 JSON 解码的重要组成部分,用于Python数据结构的可扩展JSON编码器。
在调用序列化 json.dump()
、json.dumps()
方法时,传入的参数大部分实则传给了解码器,这也是参数名一致的原因。
为了将其拓展至识别其他对象,需要子类化并实现 default()
方法于另一种返回 o 的可序列化对象的方法如果可行,否则它应该调用超类实现(来引发 TypeError
)。
源码:
通过查看源码可以看到,JSON 的反序列化方法实则是调用了 JSONDecoder
解码器。
部分源码
......
# cached encoder
if (not skipkeys and ensure_ascii and
check_circular and allow_nan and
cls is None and indent is None and separators is None and
default is None and not sort_keys and not kw):
return _default_encoder.encode(obj)
if cls is None:
cls = JSONEncoder
return cls(
skipkeys=skipkeys, ensure_ascii=ensure_ascii,
check_circular=check_circular, allow_nan=allow_nan, indent=indent,
separators=separators, default=default, sort_keys=sort_keys,
**kw).encode(obj)
参数如下:
True
时(默认为 False
)跳过不是基本对象(包括 str
, int
、float
、bool
、None
)字典的键,否则引发一个 TypeError
异常。True
时(默认为 True
),输出保证将所有输入的非 ASCII 字符转义。如果 ensure_ascii 是 false,这些字符会原样输出。False
(默认为 True
),那么容器类型的循环引用检验会被跳过并且循环引用回引发一个 OverflowError
(或者更糟的情况)。False
(默认为 True
),那么在对严格 JSON
规格范围外的 float
类型值(nan
、inf
和 -inf
)进行序列化时会引发一个 ValueError
异常。如果为 True
,则使用它们的 JavaScript 等价形式(NaN
、Infinity
和 -Infinity
)。True
时(默认为 False
)跳过不是基本对象(包括 str
, int
、float
、bool
、None
)字典的键,否则引发一个 TypeError
异常。None
会选择最紧凑的表达,即一行数据。""
,则只会添加换行符,在每个缩进前都不会有字符。(item_separator, key_separator)
元组(项分割字符,键分割字符)。indent
的存在,separators
的默认值会有两种变化,当 indent
为 None
时,会使用紧凑的一行表达,这时候的分割符会取值 (', ', ': ')
在每个分割符后都有空格,而相反在不为 None
时会取值 (',', ':')
。None
的情况下,可以手动将 separators 取值为 (',', ':')
,也就是不留空格。TypeError
。如果没有被指定,则会直接引发 TypeError
。方法功能
default(o)
在子类中实现这种方法使其返回 o 的可序列化对象,或者调用基础实现(引发 TypeError
)。
比如说,为了支持任意迭代器,你可以像这样实现默认设置:
def default(self, o):
try:
iterable = iter(o)
except TypeError:
pass
else:
return list(iterable)
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, o)
encode(o)
返回 Python o 数据结构的 JSON 字符串表达方式。例如:
>>> json.JSONEncoder().encode({"foo": ["bar", "baz"]})
'{"foo": ["bar", "baz"]}'
iterencode(o)
编码给定对象 o ,并且让每个可用的字符串表达方式。
for chunk in json.JSONEncoder().iterencode(bigobject):
mysocket.write(chunk)
exception json.JSONDecodeError(msg, doc, pos)
参数如下:
源码:
源码比较简单,这里将源码贴出
class JSONDecodeError(ValueError):
"""Subclass of ValueError with the following additional properties:
msg: The unformatted error message
doc: The JSON document being parsed
pos: The start index of doc where parsing failed
lineno: The line corresponding to pos
colno: The column corresponding to pos
"""
# Note that this exception is used from _json
def __init__(self, msg, doc, pos):
lineno = doc.count('\n', 0, pos) + 1
colno = pos - doc.rfind('\n', 0, pos)
errmsg = '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)
ValueError.__init__(self, errmsg)
self.msg = msg
self.doc = doc
self.pos = pos
self.lineno = lineno
self.colno = colno
def __reduce__(self):
return self.__class__, (self.msg, self.doc, self.pos)
演示代码:
演示手动触发异常,一般也用不上,更多是用于理解源码是如何工作的
# -*- coding: utf-8 -*-
import json
err_json = "{key: {\n'key2':value1}}}key3:value"
raise json.JSONDecodeError("json数据格式错误", err_json, len(err_json))
json.decoder.JSONDecodeError: json数据格式错误: line 2 column 27 (char 34)