如何为兼容json.dumps序列化的函数参数标注正确类型?
为支持
json.dumps的函数参数标注合适的类型 问题背景
我想为一个最终会调用json.dumps的函数参数标注类型,要求既支持默认可序列化类型,也兼容自定义JSONEncoder处理的类型。目前使用Union[List[Any], Dict[Any, Any]]存在覆盖不全的问题,还会被mypy提示Explicit "Any" is not allowed。
现有代码示例:
import json from typing import List, Dict from datetime import date def my_function_doing_stuff_then_serializing(input: Union[List[Any], Dict[Any, Any]], **kwargs) -> None: json.dumps(input, **kwargs)
希望支持的调用场景(自定义Encoder处理date类型):
import json from datetime import date from somewhere import my_function_doing_stuff_then_serializing class DateEncoder(json.JSONEncoder): def default(self, obj: Any) -> Any: if isinstance(obj, date): return obj.isoformat() return super().default(obj) my_function_doing_stuff_then_serializing([date.today()], cls=DateEncoder)
解决方案
场景1:仅支持默认json.dumps可序列化类型
如果函数只处理Python标准JSON库默认能序列化的类型,可以定义一个递归的类型别名,精准覆盖所有合法的默认序列化类型:
from typing import Union, List, Dict import json # 定义默认JSON可序列化的类型 JSONValue = Union[None, bool, int, float, str, List['JSONValue'], Dict[str, 'JSONValue']] def my_function_doing_stuff_then_serializing(input: JSONValue, **kwargs) -> None: json.dumps(input, **kwargs)
这个类型别名完全匹配json.dumps默认支持的类型集合,mypy不会再抛出Explicit "Any" is not allowed的错误。
场景2:支持自定义JSONEncoder的情况
当允许传入自定义JSONEncoder处理非默认类型时,静态类型系统无法提前预判哪些类型能被自定义Encoder兼容(因为Encoder的逻辑是动态的)。这种情况下,最合理的做法是使用Any,同时通过文档注释说明参数支持自定义Encoder适配的类型:
from typing import Any import json def my_function_doing_stuff_then_serializing(input: Any, **kwargs) -> None: """ 处理并序列化输入数据,支持通过`cls`参数传入自定义JSONEncoder处理非默认类型 """ json.dumps(input, **kwargs)
如果项目开启了mypy的disallow_explicit_any规则,可以用语义化的类型别名替代直接写Any,提升代码可读性:
from typing import Any import json # 语义化类型别名,表示支持自定义Encoder的可序列化类型 JSONEncodable = Any def my_function_doing_stuff_then_serializing(input: JSONEncodable, **kwargs) -> None: json.dumps(input, **kwargs)
这样既保留了类型标注的语义,又能避免mypy的错误提示(若项目允许使用Any)。
内容的提问来源于stack exchange,提问作者codekoriko
相关产品推荐
相关产品推荐

