使用mypy / PEP-526定义jsonable类型

时间:2018-07-11 18:00:56

标签: mypy

可以通过json.dumps转换为JSON字符串的值是: -标量:数字和字符串 -容器:映射和可迭代

Union [str,int,float,映射,可迭代]

您有更好的建议吗?

2 个答案:

答案 0 :(得分:3)

不幸的是,对PEP 484类型而言,正确键入JSON Blob很尴尬。部分原因是mypy(当前)缺少递归类型:这意味着我们能做的最好的事情就是使用与您构造的类型相似的类型。

(但是,我们可以对您的类型进行一些细化。特别地,json.Dumps(...)实际上不接受任意可迭代。例如,生成器是Iterable的子类型,但是{{ 1}}将拒绝序列化生成器。您可能想使用类似json.dumps(...)的东西。)

另一个原因是,即使我们确实有递归类型,让函数返回并集也常常导致对调用者造成很多尴尬,调用者常常需要断言或强制转换来获取它们所要使用的类型期待。 (类似地,让函数接受并集作为参数可以使实现复杂化-尽管在许多情况下,无论如何,复杂性都是您必须要做的,而不是仅仅为了满足类型检查器而编写的代码。) / p>

因此,很多人最终仅使用Sequence来表示JSON字典。显然,它不如您的签名精确,但是像这样的简单类型在实践中往往更符合人体工程学。

或者,如果您想使用类型更安全的类型,则可以尝试使用TypedDicts。基本上,您可以构造一个类型,以明确指定特定JSON Blob的外观,然后使用该类型。这是要做的更多工作,但是可以让您获得更多的类型安全性。

也就是说,如果您可以期望要处理的JSON Blob中有某种结构,那么通常这是最好的方法。 (例如,如果您正在调用某个API,并且知道它将以特定格式返回一些JSON)。如果您的程序需要处理真正任意的JSON Blob,那么恐怕您将不得不使用一种或另一种形式的不精确/动态类型。


tl; dr:

  • 您的类型需要进行一些细微调整(例如,使用Dict[str, Any]代替Sequence
  • 由于一开始很难以类型安全的方式键入任意JSON Blob,因此某些人使用了更简单的类型,例如Iterable,接受了JSON本质上是动态的,并转而使用运行时检查。
  • 如果我们可以期望我们的JSON Blob以特定的方式进行结构化,则可以使用TypedDicts(当然,与其他类型结合使用)来表示它们。

答案 1 :(得分:1)

关于引入JSONType的可能性已经进行了长时间的讨论(https://github.com/python/typing/issues/182);但是,尚未得出明确的结论。

当前建议是仅在自己的代码中定义JSONType = t.Union[str, int, float, bool, None, t.Dict[str, t.Any], t.List[t.Any]]或类似的内容。