如何在装饰器中比较多参数?编写JSON验证装饰器遇问题求助
JSON验证装饰器实现指南
首先得说下你现有代码里的几个小问题,这样我们能更好地修正方向:
- 装饰器结构不对:带参数的装饰器得先返回装饰器函数,你现在直接在里面调用
f(),会导致被装饰的函数在装饰阶段就执行了,而不是等你调用它的时候才执行,完全不符合装饰器的使用逻辑。 - 判断逻辑不靠谱:把JSON转成字符串然后检查包含关系很容易出错,比如如果键名有重叠(比如允许"name",但JSON里有"username"),就会误判。正确的做法应该是直接对比JSON的键集合。
- 异常抛出方式不对:你直接
return ValueError(...),这不会抛出异常,只是返回了一个异常对象而已,得用raise语句才行。
接下来给你一个完整的可运行实现,同时解决“支持更多参数”的问题:
# 定义带可变参数的装饰器,*allowed_keys接收所有允许的键 def mydecorator(*allowed_keys): def decorator(func): def wrapper(*args, **kwargs): # 先调用被装饰的函数,拿到要验证的JSON数据 sent_json = func(*args, **kwargs) # 把JSON的键和允许的键都转成集合,方便对比 json_keys = set(sent_json.keys()) allowed_set = set(allowed_keys) # 找出JSON中存在但不在允许列表里的键 extra_keys = json_keys - allowed_set if extra_keys: raise ValueError(f"JSON包含不允许的键: {', '.join(extra_keys)}") # 验证通过,返回原函数的结果 return sent_json return wrapper return decorator # 测试场景1:符合要求的JSON @mydecorator("first_name", "last_name") def get_valid_json(): return {"first_name": "James", "last_name": "Bond"} # 测试场景2:包含额外键的JSON @mydecorator("first_name") def get_invalid_json(): return {"first_name": "James", "last_name": "Bond", "age": 30} # 验证正确情况 print(get_valid_json()) # 输出: {'first_name': 'James', 'last_name': 'Bond'} # 验证错误情况,会抛出异常 try: get_invalid_json() except ValueError as e: print(e) # 输出: JSON包含不允许的键: last_name, age
关于“如何支持更多参数”的问题
其实上面的实现已经完美解决了这个需求:
我们用*allowed_keys这个可变参数语法,让装饰器可以接收任意数量的允许键。比如你要检查5个键,直接写@mydecorator("key1", "key2", "key3", "key4", "key5")就行,装饰器会自动把所有传入的参数收集成一个元组,转成集合后和JSON的键做对比,不管参数多少都能轻松处理。
另外补充一点:如果你的JSON是作为函数参数传入的(而不是函数返回的),只需要修改wrapper里的逻辑,去检查传入的参数即可,比如:
def wrapper(json_data, *args, **kwargs): # 直接检查传入的json_data json_keys = set(json_data.keys()) # 后续逻辑和之前一样...
内容的提问来源于stack exchange,提问作者derriadiergummi
相关产品推荐
相关产品推荐

