JSON
json作为现在最流行的传输格式,在Python中也有响应的实现方式,就是因为JSON格式的文本可以跨平台并且简单易用,所以广为流传,那么我们今天就主要探讨一下,如何熟练的应用Python的JSON库来处理json映射到文本,并且再从文本映射到对象中。我们现在就开始。
官方json库
官方的json库有很多,标准库:json 、 marshal、 pickle ,其中我最喜欢用其中的json,因为pickle 存在很多反序列化漏洞,并且是二进制类型的,json更像我们Java中的fastjson一样操作,但是还是跟fastjson有很大差别的。我们继续看。
简单用法
python
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}
from io import StringIO
io = StringIO()
json.dump(['streaming API'], io)
io.getvalue()
# '["streaming API"]'
上面这都是官方实例,我们不多说了,我们讲解一下我们工作中如何使用json进行序列化和反序列化对象。
进阶用法
假如我们的前端返回给后端一串json文本,我们如何正确的映射到对象中呢?其实对于我来讲,使用对象反而会影响Python的快速开发,直接字典用起来就完事了,别面向对象了了。但是确实对象更规范一些,我来演示一下:
{"status":1,"info":"成功","data":{"id":"52","age":"70"}}
上面是我们接收的参数,我们处理一下将其映射到对象中。
python
import json
class Response_data:
def __init__(self, id, feed_id):
super().__init__()
self.id = id
self.feed_id = feed_id
class Response:
def __init__(self, status=None, info=None, data=None) -> None:
super().__init__()
self.status = status
self.info = info
self.data = data
def to_json(self):
return {
"status": self.status,
"info": self.info,
"data": self.data.__dict__ if self.data else None
}
@staticmethod
def object_hook(d):
if "status" in d :
return Response(d['status'], d['info'], d['data'])
else:
return Response_data(d['id'],d['feed_id'])
body = '{"status":1,"info":"发布成功","data":{"id":"52","feed_id":"70"}}'
resp = json.loads(body, object_hook=Response.object_hook)
print(json.dumps(resp.to_json(),ensure_ascii=False))
上面用到了object_hook参数,这个参数主要就是用来自定义解码函数的。入参数标准反序列化后的dict,我们可以根据自己的规则转换输出为想要的格式。
我为什么需要在object_hook中写一个if判断呢?主要是因为object_hook参数反序列化时,是递归出来的,因为我的json文本是嵌套结构,所以嵌套几层就会递归几层,所以我需要先封装好Response_data后,才能继续封装Response,这根Java中的JSON序列化天差地别,Java中的序列化,我们可不用管这么多,但是Python不仅需要我们自己指定参数名称,而且还得处理好嵌套。
如果在解析中文时遇到问题,可能是因为默认的编码格式不支持中文字符。你可以尝试使用ensure_ascii=False参数来解决这个问题。这个参数会禁用ASCII编码,从而保留中文字符的原始形式。
多说一句
json库是Python2.6版中加入的。如果您使用更早版本的Python, 可以通过PyPI获取 simplejson 库。
json 类型转换到 python 的类型对照表:
JSON | Python |
---|---|
object | dict |
array | list |
string | unicode |
number (int) | int, long |
number (real) | float |
true | True |
false | False |
null | None |
三方json库
demjson
Demjson 是 python 的第三方模块库,可用于编码和解码 JSON 数据,包含了 JSONLint 的格式化及校验功能。demjson也支持hook。有两种配置的方式:decode函数配置和set_hook函数配置。
Github 地址:github.com/dmeranda/de...
官方地址:deron.meranda.us/python/demj...
decode函数可以指定很多参数,其中就包括hook函数。hook函数的指定是使用键值对的方式,键是hook函数的名称,值是hook函数。
由于安装报错,需要降低setuptools到57.5.0版本,所以我就不去实验了。
orjson
在日常的开发工作中,我们经常需要将一些数据存储为JSON格式,最常用的就是Python原生的JSON库,但是该库速度较慢, 当数据量过大时,使用不便。而orjson的功能强大,它支持多种类型的数据序列化,开发者还可以根据需要定制化输出, 与其他第三方JSON库相比,效率更高。
我们来看下他是如何运作的。下面是一个使用 dataclasses 模块的示例:
python
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
# 假设您有一个包含 JSON 数据的字符串
json_data = '{"name": "xiaoyu", "age": 18}'
# 使用 orjson 反序列化 JSON 数据
import orjson
data_dict = orjson.loads(json_data)
# 将字典转换为 Person 对象
person = Person(**data_dict)
# 现在,您可以像访问对象属性一样访问 person 对象的属性
print(person.name) # 输出 "xiaoyu"
print(person.age) # 输出 18
这么一看确实跟官方json没啥区别,官方json也能做到,但是我们再将person对象dumps出来时,json是不支持的,orjson是可以支持的。
python
orjson.dumps(person)
option参数
orjson还支持使用option参数可以定制序列化的结果。太多的我就不列举了,我就简单举一个日期格式的例子吧,毕竟日期格式基本上我们工作中都需要做一下处理。
option=orjson.OPT_NAIVE_UTC: 这个选项会使得序列化的日期时间对象以字符串的形式呈现,而不是默认的 ISO 8601 格式。这在一些情况下可能更方便,例如与其他系统进行数据交换时。
python
import orjson
from datetime import datetime
data = {"name": "xiaoyu", "dob": datetime(2020, 5, 1)}
json_data = orjson.dumps(data, option=orjson.OPT_OMIT_MICROSECONDS)
print(json_data.decode())
为什么需要decode呢?主要是因为orjson返回的二进制,如果想要str类型所以需要解码。
总结
JSON是一种流行的数据传输格式,Python中有多种处理JSON的方式。官方的json库是最常用的,它提供了简单的用法来序列化和反序列化JSON文本。此外,它还支持自定义解码函数,可以将JSON映射到对象中。
在使用官方json库时,可以使用dumps函数将Python对象转换为JSON文本,也可以使用loads函数将JSON文本转换为Python对象。如果需要自定义解码函数,可以使用object_hook参数来实现。
除了官方的json库,还有一些第三方的库可供选择。例如,demjson库提供了JSON数据的编码和解码功能,并支持hook函数。另外,orjson库是一个高效的JSON库,支持多种数据类型的序列化,并提供了定制化输出的选项。
总之,掌握Python的JSON处理库对于处理JSON数据非常重要,可以帮助我们在项目开发中更加高效地处理JSON数据。