接口自动化之响应数据封装
在使用requests实现接口自动化时,接口响应的数据没有代码提示,要获取某个接口字段就需要通过
[xxx]
的方式来获取,实际开发过程中希望能通过.
的方式来获取到某个接口响应属性。
方式一、使用dataclass
dataclass是python3.7新推出的特性之一
from dataclasses import dataclass
@dataclass
class OrderVo:
id: int
orderNo: str
...
status: str = 'CLOSED' # 此处可以设置默认值,如果没有传值,则使用这个默认值
使用方式:
OrderVo(**response.json())
但是在实际使用过程中2个问题
- 接口增加字段后,初始化会报错,提示参数多了
- 后端介绍字段后,初始化又会报错,提示参数少了(此处虽然可以通过添加默认值来规避,但是频繁的修改的Vo的定义也会很麻烦)
- 如果对象是嵌套表示的,则每次都需要在__post_init__中定义嵌套对象要如何初始化
方式二、自定义响应对象
首先是元类的定义
import re
from types import GenericAlias
class ModelMetaclass(type):
def __new__(cls, name, bases, attrs):
if name == 'Model':
return type.__new__(cls, name, bases, attrs)
attrs['__default__'] = {} # 此处用来保存数据的默认值
__remove__ = []
for key, value in attrs.items():
if key.startswith('__'): # 跳过双下划綫开头的属性
continue
attrs['__default__'][key] = value
__remove__.append(key)
for k in __remove__:
attrs.pop(k)
return type.__new__(cls, name, bases, attrs)
然后是定义基类
class Model(dict, metaclass=ModelMetaclass):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for key, value in self.__annotations__.items():
if key in self:
if isinstance(value, ModelMetaclass):
self[key] = value(**self[key])
elif isinstance(value, GenericAlias):
if self[key]:
self[key] = [value.__args__[0](**v) for v in self[key]]
continue
# 通过__default__拿到默认值,在初始化的时候将默认值赋值给属性,如果没有默认值且初始化的时候不传值就报错,则.get改为[]的方式来获取值即可
self[key] = self.__default__.get(key, None)
def __getattr__(self, item):
try:
return self[item]
except KeyError:
raise AttributeError(f"{self.__class__.__name__!r} object has no attribute {item!r}")
def __getattribute__(self, item):
return super().__getattribute__(item)
def __setattr__(self, item, value):
self[item] = value
__show__ = None # 定义数据的展示字段,如果为None,则展示全部的数据
def __str__(self):
show = self.__show__
if not show:
show = self.__annotations__.keys()
if isinstance(show, str):
show = re.split(r'[,\s]+', show.strip()) # 展示字段支持通过,和空格进行分割
val = ', '.join(f"{key}={self.__getattr__(key)!r}" for key in show)
return f'{self.__class__.__name__}({val})'
__repr__ = __str__
最后是使用效果
# 定义两个对象
class Book(Model):
name: str
price: float = 3.4
author: str = 'none'
__show__ = 'name'
class Student(Model):
name: str
age: int = 3
books: list[Book]
__show__ = 'name'
print(Student())
# Student(name=None)
print(Student(name='zs'))
# Student(name='zs')
print(Student().books)
# None
print(Student(**{'name': 'tom', 'age': 10, 'books': [{'name': 'sg', 'price': 1.2}]}).books)
# [Book(name='sg')]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步