python序列化原理与格式转换

引言

本篇想从序列化开始,讲述python的xml、json以及protobuf文件格式,并实现xml到json以及json到protobuf之间格式的互转与xml增删改查操作。另外关于ujson与bjson等格式类型,会在最后进行总结。

序列化与反序列化

互联网的产生带来了机器间通讯的需求,而互联通讯的双方需要采用约定的协议,序列化和反序列化属于通讯协议的一部分。通讯协议往往采用分层模型,不同模型每层的功能定义以及颗粒度不同,例如:TCP/IP协议是一个四层协议,而OSI模型却是七层协议模型。在OSI七层协议模型中展现层(Presentation Layer)的主要功能是把应用层的对象转换成一段连续的二进制串,或者反过来,把二进制串转换成应用层的对象–这两个功能就是序列化和反序列化。一般而言,TCP/IP协议的应用层对应与OSI七层协议模型的应用层,展示层和会话层,所以序列化协议属于TCP/IP协议应用层的一部分。本文对序列化协议的讲解主要基于OSI七层协议模型。

上一段引用自美团2015年的 序列化和反序列化 . 不知道为啥看的人很少,但我觉得这篇文章概念都介绍得挺深的,我看得也受益匪浅,所以本篇的很多概念都会出自于这篇和几篇外文文献,我会在最后的参考文献里标注出来。那么经过上面这一段话,我们就能总结出序列化和反序列化的原理:

  • 序列化: 将数据结构或对象转换成二进制串的过程
  • 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程

在python中,序列化即是将内存中的字典、列表、集合以及各种对象保存到一个二进制串或者一个文件中,前者叫序列化,后者叫序列化加持久化,而只有根据序列化后的数据流,才能在网络传输中比较快的进行解析与通信。

再举个通俗点的例子: 你在打游戏过程中,打累了,停下来,想过两天再玩,两天之后,游戏又从你上次停止的地方继续运行,你上次游戏的进度肯定保存到硬盘上了,那么是以何种形式呢?游戏过程中产生的很多临时数据是不规律的,可能在你关掉游戏时正好是10个列表,3个嵌套字典的数据集合在内存里面,需要存下来,你如何存?把列表变成文件里的多行多列形式?那嵌套字典呢?根本没法存吧,所以,若是有种办法可以直接把内存数据存到硬盘上,下次程序再启动,再从硬盘上读出来,还是原来的格式,那是最好的,所以这就是我们要说的序列化。

python有提供非常多的序列化工具,比较常用的便是下表所见:

要实现的功能 可以使用的api
将Python数据类型转换为(json)字符串 json.dumps()
将json字符串转换为Python数据类型 json.loads()
将Python数据类型以json形式保存到本地磁盘 json.dump()
将本地磁盘文件中的json数据转换为Python数据类型 json.load()
将Python数据类型转换为Python特定的二进制格式 pickle.dumps()
将Python特定的的二进制格式数据转换为Python数据类型 pickle.loads()
将Python数据类型以Python特定的二进制格式保存到本地磁盘 pickle.dump()
将本地磁盘文件中的Python特定的二进制格式数据转换为Python数据类型 pickle.load()
以类型dict的形式将Python数据类型保存到本地磁盘或读取本地磁盘数据并转换为数据类型 shelve.open()
将python字典数据转换为xml格式 xmltodict.unparse()
将xml文件格式转换为python字典数据 xmltodict.parse()

其中xmltodict不是python内置包,需要pip install xmltodict,首先开始介绍xml格式的书写规范。

xml介绍与比较

本节我可能会用一段不小的篇幅,以及几段代码来总结一下xml,因为最近接触这个的比较多,如果不感兴趣的可以跳过,因为后面基本也不会再提到,我只是想写点笔记,如果以后有用到可以回头再看。

XML是一种常用的序列化和反序列化协议,具有跨机器,跨语言等优点。 XML历史悠久,其1.0版本早在1998年就形成标准,并被广泛使用至今。XML的最初产生目标是对互联网文档(Document)进行标记,所以它的设计理念中就包含了对于人和机器都具备可读性。 但是,当这种标记文档的设计被用来序列化对象的时候,就显得冗长而复杂(Verbose and Complex)。 XML本质上是一种描述语言,并且具有自我描述(Self-describing)的属性,所以XML自身就被用于XML序列化的IDL。 标准的XML描述格式有两种:DTD(Document Type Definition)和XSD(XML Schema Definition)。作为一种人眼可读(Human-readable)的描述语言,XML被广泛使用在配置文件中,例如O/R mapping、 Spring Bean Configuration File 等。

我记得我刚开始学编程的时候,其实接触xml是比较多的,那个时候没有一条明确的主线瞎学,很多应用提供的配置文件还是xml,我就只能照葫芦画瓢模仿着来搭建,但随着技术的提升,以及选定python,似乎开始与xml渐行渐远,而直到最近,因为一个图片标注信息是由csv保存而需要转换成xml,之后还要对标注信息修改,让我意识到xml的存在必要性。即使是今天,xml看似已经被淘汰,但不会消亡,因为它的易于扩展性以及安全性。具体可以看知乎某帖:为什么XML这么笨重的数据结构仍在广泛应用?

XML全称EXtensible Markup Language,翻译为可扩展置标语言,在python中专门有包为xml,实例为:

import xml.etree.ElementTree as ET

new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml, "name", attrib={
   "enrolled": "yes"})
age = ET.SubElement(name, "age", attrib={
   "checked": "no"})
sex = ET.SubElement(name, "sex")
sex.text = '33'
name2 = ET.SubElement(new_xml, "name", attrib={
   "enrolled": "no"})
age = ET.SubElement(name2, "age")
age.text = '19'

et = ET.ElementTree(new_xml)  # 生成文档对象
et.write("test.xml", encoding="utf-8", xml_declaration=True)

ET.dump(new_xml)  # 打印生成的格式
"""
<namelist><name enrolled="yes"><age checked="no" /><sex>33</sex></name><name enrolled="no"><age>19</age></name></namelist>
"""

输出的结果基本就是标准xml格式数据了,了解了python怎么生成xml的,我们还可以就此xml进行json转换:

import xmltodict
import json

a = """
<namelist><name enrolled="yes"><age checked="no" /><sex>33</sex></name><name enrolled="no"><age>19</age></name></namelist>
"""

order_dict = xmltodict.parse(a)
json_data = json.dumps(order_dict)
print(json_data)
"""
{"namelist": {"name": [{"@enrolled": "yes", "age": {"@checked": "no"}, "sex": "33"}, {"@enrolled": "no", "age": "19"}]}}
"""

将json或者dict转xml也是基于xmltodict.unparse就行,可以对照上面的表格,具体的操作我就不再列举了。另外我想记录一下之前我业务根据csv转xml的例子:

from xml.etree.ElementTree impo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

submarineas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值