前言:
本文默认你了解json
,对Python的json
模块也有基本的了解
正文
1. 总结
Python的json
模块解决的问题是三种格式的转换:
- 字符串
- Python对象
- 文件
Python对象包括:
所有Python基本数据类型,列表,元组,字典,自己定义的类,等等等等,当然除了字符串
Python的json
模块其实没有多少内容,
说起来的话常用的一共有4个方法:
json.dumps
json.dump
json.loads
json.load
你可以认为这4个方法就是json
模块的全部
这四个方法实现了三种格式之间的互相转换:
2. 互相转化:
这四个方法之间有如下关系
Python对象与字符串互相转换:
python对象 ⇢ \dashrightarrow ⇢ 字符串:json.dumps
字符串 ⇢ \dashrightarrow ⇢ Python对象:json.loads
Python对象与数据文件互相转换:
json文件 ⇢ \dashrightarrow ⇢ Python对象:json. load
Python对象 ⇢ \dashrightarrow ⇢ json文件:json.dump
其他类型转Python对象:
load(s)
其他类型写入json文件:
dump
实战
只有Python对象才可以转字符串,而文件是不可以直接转字符串的
文件转字符串:load
⇢ \dashrightarrow ⇢ dumps
有没有发现字符串转Python对象用loads
,文件转Python对象用load
,而字符串和Python对象转文件都是用dump
?
Because dump
接收的是obj
对象,我们可以看下dump
方法定义是的签名:
def 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):
"""Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
``.write()``-supporting file-like object).
...
"""
第一参数就是obj
OK,问题又来了,我们看下dumps
方法定义时的签名:
def 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):
"""Serialize ``obj`` to a JSON formatted ``str``.
...
"""
dumps
方法接收的也是obj
类型的对象,但是为什么文件不能直接转字符串呢?
因为dumps接收的obj对象需要进行json
序列化,而在Python里文件的类型为TextIOWrapper
,它没有进行json
序列化。
大家可以看下dump
和dumps
方法定义的下面的注释,它们接收的obj
对象都是需要进行json
序列化的。:
Serialize ``obj`` to a JSON formatted ``str``
OK,问题又来了,我们应该怎么进行json
序列化呢?
我们现在定义一个Person
类:
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
p = Person("马云", 54, "man")
print(json.dumps(p))
运行的时候会报错: Person
没有进行JSON序列化:
为Person
定义一个JSON序列化的方法(其实就是类实例转换为字符串), 然后在调用的时候显式指定, 我们再试一下:
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def toJSON(self):
return {
"name": self.name,
"age": self.age,
"gender": self.gender
}
p = Person("马云", 54, "man")
a = json.dumps(p, default=Person.toJSON, ensure_ascii=False)
print(a)
这样就好了:
OK,那么我我们又怎么进行反序列化,把一个字符串反序列化成一个指定的类(而不是字典)呢?
很简单,也是定义一个方法用于把字符串转为类实例,然后在json.loads
的时候指定就可以了,代码如下:
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def toJSON(self):
return {
"name": self.name,
"age": self.age,
"gender": self.gender
}
@staticmethod
def parseJSON(dct):
if isinstance(dct, dict):
p = Person(dct["name"], int(dct['age']), dct['gender'])
return p
return dct
a = """{"name": "马云", "age": 54, "gender": "man"}"""
b = json.loads(a, object_hook=Person.parseJSON)
print(b)
打印结果: