|
JSON
JSON作为目前最流行的传输格式,在Python中也有相应的实现方式。由于JSON格式的文本可以跨平台并且简单易用,因此被广泛传播。因此,我们今天的主要讨论内容是如何熟练地应用Python的JSON库来处理将JSON映射到文本,以及如何从文本映射到对象中。现在,让我们开始探讨这个话题。
官方json库
在Python中,官方提供了多个JSON库,包括标准库中的json、marshal和pickle。其中,我个人比较喜欢使用json库,因为pickle存在一些反序列化漏洞,并且它处理的是二进制类型的数据。相比之下,json更类似于我们在Java中使用的fastjson,但它们之间仍然存在一些明显的差异。接下来,我们继续深入了解一下。
简单用法
- 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进行对象的序列化和反序列化。
进阶用法
当前端返回给后端一串JSON文本时,我们可以使用json.loads()方法将其正确映射到Python对象中。这个过程称为反序列化。使用对象来处理数据会更规范一些,尽管对于一些快速开发来说,直接使用字典可能更方便。不过,我可以给你演示一下如何使用对象进行反序列化。
首先,我们可以定义一个类来表示我们要映射的对象,然后利用json.loads()方法将JSON文本转换为字典。接着,我们可以使用字典的键值对来为对象的属性赋值。这样,我们就成功地将JSON文本映射到了对象中。让我来给你演示一下:
{"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参数。object_hook参数的主要作用是用来自定义解码函数。它的入参是标准反序列化后的字典,我们可以根据自己的规则将其转换为所需的格式。
为什么我需要在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 的类型对照表:
JSONPythonobjectdictarrayliststringunicodenumber (int)int, longnumber (real)floattrueTruefalseFalsenullNone三方json库
demjson
Demjson是一个Python的第三方模块库,它提供了编码和解码JSON数据的功能,并且还包含了JSONLint的格式化和校验功能。此外,Demjson还支持hook,可以通过decode函数配置和set_hook函数配置两种方式进行配置。
你可以在以下网址找到Demjson的Github地址:https://github.com/dmeranda/demjson。同时,你也可以在官方地址http://deron.meranda.us/python/demjson/上了解更多关于Demjson的信息。
decode函数是Demjson提供的一个功能强大的函数,它可以接受多个参数,其中包括hook函数。通过键值对的方式指定hook函数,键是hook函数的名称,而值是hook函数本身。
如果你在安装Demjson时遇到了报错,可能是因为需要降低setuptools的版本到57.5.0。不过我就不进行实验和验证了。
orjson
在日常的开发工作中,我们经常需要将一些数据存储为JSON格式。而最常用的方法是使用Python原生的JSON库。然而,我们发现该库的速度较慢,特别是当数据量过大时,使用起来非常不便。幸运的是,我们发现了orjson这个强大的工具,它不仅支持多种类型的数据序列化,还可以根据开发者的需求进行定制化输出。与其他第三方JSON库相比,orjson具有更高的效率,因此在处理大量数据时,它是一个更好的选择。
我们来看一下它是如何运作的。下面是一个使用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模块也能实现相同的功能。但是当我们尝试将person对象转换成字符串时,官方的JSON模块无法完成这个任务,而orjson则可以轻松胜任。option参数
orjson还支持使用option参数来定制序列化的结果。当然,还有很多其他的选项可以使用,但是由于太多了,我就不一一列举了。不过,我可以简单举一个日期格式的例子,因为在我们的工作中,通常需要对日期格式进行处理。
option=orjson.OPT_OMIT_MICROSECONDS: 序列化的日期时间对象将以字符串形式呈现,而不是默认的 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())
复制代码 为什么需要进行解码呢?原因主要在于orjson返回的是二进制数据,而我们需要将其转换为字符串类型,因此需要进行解码操作。
总结
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数据。
来源:https://www.cnblogs.com/guoxiaoyu/p/17975802
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|