JSON
json作为现在最盛行的传输格局,在Python中也有呼应的实现方式,便是因为JSON格局的文本能够跨平台而且简略易用,所以广为流传,那么咱们今日就主要讨论一下,怎么娴熟的运用Python的JSON库来处理json映射到文本,而且再从文本映射到目标中。咱们现在就开始。
官方json库
官方的json库有许多,规范库:json 、 marshal、 pickle ,其间我最喜欢用其间的json,因为pickle 存在许多反序列化漏洞,而且是二进制类型的,json更像咱们Java中的fastjson相同操作,可是还是跟fastjson有很大不同的。咱们继续看。
简略用法
import json
json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
# '["foo", {"bar": ["baz", null, 1.0, 2]}]'
print(json.dumps(""foobar"))
# ""foobar"
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″}}
上面是咱们接纳的参数,咱们处理一下将其映射到目标中。
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 模块的示例:
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是能够支撑的。
orjson.dumps(person)
option参数
orjson还支撑运用option参数能够定制序列化的结果。太多的我就不列举了,我就简略举一个日期格局的例子吧,究竟日期格局基本上咱们作业中都需求做一下处理。
option=orjson.OPT_NAIVE_UTC: 这个选项会使得序列化的日期时间目标以字符串的形式出现,而不是默许的 ISO 8601 格局。这在一些情况下或许更方便,例如与其他体系进行数据交换时。
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数据。