前几天有同事问如何将一个json字符串反序列化为实体,当时只是简单找了一下方案,并未对这个事情做深入的了解。一致感觉这个挺有意思于是今晚就搜索了一些资料并作了测试,感兴趣的同学可以进一步深入料及。总而,感觉python的就是可以写很少代码,引入一些现有包就可以轻易实现自己想要的功能。
单层实体:
自定义一个单层实体公共类JsonClass.py:
#!/usr/bin/python import json class JsonClass(object): def to_json_string(self): return json.dumps(self, default=lambda obj: obj.__dict__) def from_json_string(self, json_string): data = json.loads(json_string) for key in self.__dict__.keys(): setattr(self, key, data[key])
根据自己的需要反序列化的json字符串定义实体:
{"timestamp": 1560948789.5293133, "name": "a", "id": 1}
自定义实体Task.py
from com.dx.test.JsonClass import JsonClass class Task(JsonClass): def __init__(self, id=None, name=None, timestamp=None): self.id = id self.name = name self.timestamp = timestamp
测试类TaskTest.py
#!/usr/bin/python import time from com.dx.test.Task import Task if __name__ == \'__main__\': # 序列化 task = Task(1, "a", time.time()) print(task.to_json_string()) # 反序列化 json_string = \'{"timestamp": 1560948789.5293133, "name": "a", "id": 1}\' task = Task() task.from_json_string(json_string) print(task.id)
Debug后截图效果:
多层实体:
方案一(采用自定函数解析实体):
自定义json_deserialize函数实现多层解析:
import json def json_deserialize(json_data, obj): py_data = json.loads(json_data) dic2class(py_data, obj) \'\'\' Dict convert to Class 通过setattr函数赋值属性,如果有值就赋值属性和值 \'\'\' def dic2class(py_data, obj): for name in [name for name in dir(obj) if not name.startswith(\'_\')]: if name not in py_data: setattr(obj, name, None) else: value = getattr(obj, name) setattr(obj, name, set_value(value, py_data[name])) \'\'\' 设置虚拟类属性值 \'\'\' def set_value(value, py_data): if str(type(value)).__contains__(\'.\'): # value 为自定义类 dic2class(py_data, value) elif str(type(value)) == "<class \'list\'>": # value为列表 if value.__len__() == 0: # value列表中没有元素,无法确认类型 value = py_data else: # value列表中有元素,以第一个元素类型为准 child_value_type = type(value[0]) value.clear() for child_py_data in py_data: child_value = child_value_type() child_value = set_value(child_value, child_py_data) value.append(child_value) else: value = py_data return value
根据自己json字符串自定义实体:
class Meta: currentPage = 0 pageSize = 0 realSize = 0 startIndex = 0 totalCount = 0 totalPages = 0 class Data: centerCode = "" centerName = "" createTime = "" createUser = "" createUserId = "" districtCode = "" districtName = "" groupCode = "" groupName = "" id = 0 latitude = "" longitude = "" plazaCode = "" plazaName = "" tenantId = "" updateTime = "" updateUser = "" updateUserId = "" version = 0 class Result: data = [Data()] message = "" meta = Meta() status = 0
解析实体测试类:
#!/usr/bin/python import requests import json from com.dx.test.SelfDefParseJson import json_deserialize from com.dx.test.Result import Result url = "http://wdspinspector.intra.uat.beyonds.gw/phoenix/inspector/v1/baseinfos"; headers = { "tenantId": "xx", } params = { "p": 1, "ps": 20, "groupCode": "xx" } response = requests.get(url, params=params, headers=headers) responseJsonFormat = json.dumps(response.json(), sort_keys=True, indent=4, separators=(\',\', \': \')) result = Result() json_deserialize(responseJsonFormat, result)
Debug效果
方案二(安装from addict import Dict,任何层json都可以反序列化):
这种方式比较简单,只需要安装addict包。
Installing
You can install via pip
pip install addict
or through conda
conda install addict -c conda-forge
Addict runs on Python 2 and Python 3, and every build is tested towards 2.7, 3.6 and 3.7.
测试代码:
#!/usr/bin/python import requests import json from com.dx.test.Result import Result from addict import Dict url = "http://xxx/xx/xx"; headers = { "tenantId": "xx", } params = { "p": 1, "ps": 20, "groupCode": "xx" } response = requests.get(url, params=params, headers=headers) dict = Dict(response.json()) print(dict.data[0].plazaName) print(dict.meta.totalCount)
Debug效果