Python实现JSON序列化和反序列化
在我的应用中,序列化就是把类转成符合JSON格式的字符串,反序列化就是把JSON格式的字符串转换成类。C#的话直接用Newtonsoft.JSON就可以了,非常好用。本来以为python也会有类似的库,但是貌似并没有。网上查了一些python用来实现JSON序列化和反序列化的方法,用的最多的就是json.loads, json.dumps。
# 序列化:将Python对象转换成json字符串
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) # 反序列化:将json字符串转换成Python对象
loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
# 序列化:将Python对象转换成json字符串并存储到文件中
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) # 反序列化:读取指定文件中的json字符串并转换成Python对象
load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
包含自定义类的序列化例子:
from typing import List class Address:
def __init__(self,country,city):
self.country=country
self.city=city class Student:
def __init__(self,name,age,sex,address):
self.name=name
self.age=age
self.sex=sex
self.address=address class School:
def __init__(self,name,address:Address,students:List[Student]):
self.name=name
self.address=address
self.students=students import json addr1=Address('China','Beijing')
stu1=Student('lily',20,'female',Address('China','Shanghai'))
stu2=Student('tom',23,'male',Address('China','Shenzhen'))
sch1=School('MathSchool',addr1,[stu1,stu2]) # 先把python对象转换为dict对象,进而才能实现序列化
json_data=json.dumps(sch1,default=lambda o:o.__dict__,indent=2)
print(json_data)
输出结果为:


{
"name": "MathSchool",
"address": {
"country": "China",
"city": "Beijing"
},
"students": [
{
"name": "lily",
"age": 20,
"sex": "female",
"address": {
"country": "China",
"city": "Shanghai"
}
},
{
"name": "tom",
"age": 23,
"sex": "male",
"address": {
"country": "China",
"city": "Shenzhen"
}
}
]
}
序列化结果
再把生成的json_data反序列化
sch2=School(**json.loads(json_data))
print(type(sch2))
print(type(sch2.students))
print(type(sch2.address))
输出的结果为:
<class '__main__.School'>
<class 'list'>
<class 'dict'>
可见,这样的反序列化无法直接生成School类中的address属性和students属性。address的类型仍为dict,而students的类型是list。因此需要再把address的dict转换为Address,把students的list转换成List[Student]。
sch2=School(**json.loads(json_data))
sch2.address=Address(**json.loads(json.dumps(sch2.address)))
students=[]
for stu in sch2.students:
students.append(Student(**json.loads(json.dumps(stu))))
sch2.students=students
也就是说,要这样才能生成一个完整的School类。总感觉太麻烦了,不像用newtonsoft.json那么方便。于是在网上搜到了Refs[2]这篇帖子,用了里面的方法,其实这个方法就是构造了一个创建类的Structure基类。这个方法对于List[Student]这种属性我依然不能很好的解决,总感觉就差了一点点,但是我python用的没有很熟练,也只能这样了。Structure基类的代码为:
class Structure(object):
_fields=[] def __init_arg(self,expected_type,value):
if isinstance(value,expected_type):
return value
else:
return expected_type(**value) def __init__(self, **kwargs):
field_names,field_types = zip(*self._fields)
assert([isinstance(field_name,str) for field_name in field_names])
assert([isinstance(type_,type)for type_ in field_types]) for field_name,field_type in self._fields:
setattr(self,field_name,self.__init_arg(field_type, kwargs.pop(field_name))) if kwargs:
raise TypeError('Invalid arguments(s):{}'.format(','.join(kwargs)))
继承该类,那么School, Address, Student类分别为:
class Address(Structure):
_fields=[('country',str),('city',str)] class Student(Structure):
_fields=[('name',str),('age',int),('sex',str),('address',Address)] class School(Structure):
_fields=[('name',str),('address',Address),('students',list)]
序列化和反序列化:其中序列化还是使用json,反序列化则没有使用json
import json addr=Address(**{'country':'China','city':'Beijing'})
stu1=Student(**{'name':'lily','age':18,'sex':'female','address':addr})
stu2=Student(**{'name':'tom','age':19,'sex':'male','address':addr})
sch=School(**{'name':'mathSchool','address':addr,'students':[stu1,stu2]}) # 序列化sch对象,生成字符串
json_data=json.dumps(sch,default=lambda o:o.__dict__,indent=2) # 将json_data字符串转换为dict
data=json.loads(json_data) # 反序列化data,得到sch1对象
sch1=School(**data) # 反序列化可以直接获取到sch1.address对象,但是对于students对象还是不行
print(type(sch1.address)) # list类型的students属性还是要这样生成一下
students=[]
for stu in sch1.students:
students.append(Student(**stu)) sch1.students=students
Refs:
python:序列化与反序列化(json、pickle、shelve) - 秋寻草 - 博客园 (cnblogs.com)
Deserializing nested dictionaries into complex, typed(!) python objects (seanjohnsen.com)
Python实现JSON序列化和反序列化的更多相关文章
- python处理JSON 序列化与反序列化
#序列化 >>> import json>>> d={"key":"value"}>>> d{'key': ...
- 【Python】Json序列化和反序列化模块dumps、loads、dump、load函数介绍
1.json.dumps() json.dumps()用于将dict类型的数据转成str,因为如果直接将dict类型的数据写入json文件中会发生报错,因此在将数据写入时需要用到该函数. 转换案例: ...
- python json序列化与反序列化操作
python json序列化与反序列化操作 # dumps() dict-->str 序列化 # loads() str---dict 反序列化 result1 = json.dumps({'a ...
- python 3 json 序列化
python 3 json 序列化 我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特 ...
- DotNet的JSON序列化与反序列化
JSON(JavaScript Object Notation)JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式.在现在的通信中,较多的采用JSON数据格式,JSON有 ...
- C#中JSON序列化和反序列化
有一段时间没有到博客园写技术博客了,不过每天逛逛博客园中大牛的博客还是有的,学无止境…… 最近在写些调用他人接口的程序,用到了大量的JSON.XML序列化和反序列化,今天就来总结下json的序列化和反 ...
- Newtonsoft.Json 序列化和反序列化 时间格式
From : http://www.cnblogs.com/litian/p/3870975.html 1.JSON序列化 string JsonStr= JsonConvert.SerializeO ...
- Net中JSON序列化和反序列化处理(日期时间特殊处理)
0 缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ...
- Newtonsoft.Json 序列化和反序列化 时间格式 [转]
1.JSON序列化 string JsonStr= JsonConvert.SerializeObject(Entity); eg: A a=new A(); a.Name="Elain ...
随机推荐
- 676. Implement Magic Dictionary
Implement a magic directory with buildDict, and search methods. For the method buildDict, you'll be ...
- default和delete
在C++中,有四类特殊的成员函数,分别为:默认构造函数,默认析构函数,默认拷贝构造函数,默认赋值运算符.他们的作用为创建.初始化.销毁.拷贝对象. 虽然在类A中什么都没有定义,但是编译会通得过,因为编 ...
- docker镜像中文件丢失
背景介绍 笔者创建了一个镜像,然后在不同的主机上启动,发现有的能启动,有的却不行,报错信息为找不到文件. 犹记得当初有人介绍,只要docker镜像做好了,拿到任何地方都可以用,此处好像不成呢,好诡异的 ...
- Kubernetes之日志和监控(十五)
一.日志和监控 1.1.Log 1.1.1.容器级别 通过docker命令查看容器级别的日志 docker ps --->containerid docker logs containerid ...
- react直接使用bootstrap失效的原因
react用的是className!而不是class~
- uni微信小程序优化,几行代码就能省100kb的主包空间?
不是标题党,我们公司的项目确确实实是省下了100kb的主包空间,而且还是在没有牺牲任何的性能和业务的前提下实现的. 但是100kb是根据项目大小,所以你用这个插件可能省下超过100kb或者更少. 直接 ...
- C#Xml的三种创建方式(或者是两种?)和增删改查
一.Xml的创建方式 Xmlwriter(流式读取,Stream) 写过了:https://www.cnblogs.com/dengzhekaihua/p/15438493.html 这种方法虽然快, ...
- Docker版本Jenkins的使用
一. 什么是Jenkins Jenkins是当前非常流行的一款持续集成工具,可以帮助大家把更新后的代码自动部署到服务器上运行. 二. 为什么用docker版的Jenkins Jenkins主要有三种安 ...
- c语言中数组的定义和java中数组定义的一些区别
感谢原文:https://blog.csdn.net/gzwdz778/article/details/79799408 一维情况下: c中,数组的声明需要给出数组的维数,比如: int arr[5] ...
- MyEclipse工程中Java Build Path中的JDK版本和Java Compiler Compiler compliance level的区别
感谢大佬:https://blog.csdn.net/shan9liang/article/details/17266519 问题起源: 今天再在ESB调用WebService测试,需要在jboss上 ...