json 嵌套dict的类型提示

bz4sfanl  于 2023-08-08  发布在  其他
关注(0)|答案(3)|浏览(135)

我在Python脚本中解析的数据结构是一个json文件,在json.load(file_handle)之后,类型为<class 'dict'>。到目前为止一切顺利。现在,对于一个使用它作为输入参数的函数,我需要一个解析的json的类型提示。我在类型文档中读到,对于dict s作为参数,我应该使用Mapping[key_type, value_type]

from typing import Mapping

def foo(json_data: Mapping[str, str]) -> None:
    ...

字符串
我解析的json有str类型的键和str类型的值,但通常情况下,它的结构是高度递归的。因此,一个值更有可能是一个dict,带有str键,甚至是这样的dict s作为值。它是非常嵌套的,直到最深层次,最后一个dict最终有str键和str值。
那么,如何更精确地表示这个数据结构呢?我在想一些东西,沿着this question的路线,它可能是:

Union[Mapping[str, str], Mapping[str, Mapping]]


但它似乎只代表了一个层次的递归。有没有更好的方式来输入提示呢?

xzv2uavs

xzv2uavs1#

简单语句

您可以简单地使用Mapping[K, V]作为另一个Mapping的值。假设你的json看起来像这样:

{
   "person_1": {"money": 1000},
   "person_2": {"money": 1000}
}

字符串
在这种情况下,您可以使用如下类型提示:

Mapping[str, Mapping[str, int]]

硬词

但假设你有更复杂的东西,像这样:

{
    "person_1": {
        "money": 1000,
        "job": "coder",
    }
}


那你怎么能输入hint呢?你可以使用Union(从输入)来做这样的事情:

Mapping[str, Mapping[str, Union[str, int]]]


但是现在我们会遇到一个问题,比如mypy认为our_dict["person_1"]["job"]的类型是Union[str, int]
这并没有错,毕竟这是我们告诉它的。在这里可以使用来自typing_extensionsTypedDict

from typing_extensions import TypedDict

class Person(TypedDict):
    money: int
    job: str

# type hint you would use in your function:
Mapping[str, Person]

注意:在python中3.8TypedDict是typing的一部分

q5iwbnjs

q5iwbnjs2#

现在,mypy和其他类型检查器支持递归定义。Json类型的一个(有点)完整的例子是:

import typing as t

JsonType: t.TypeAlias = t.List['JsonValue'] | t.Mapping[str, 'JsonValue']
JsonValue: t.TypeAlias = str | int | float | None | JsonType

def foo(json_data: JsonType) -> None:
    """Your implementation here"""

字符串
这应该是类型检查。

i2loujxw

i2loujxw3#

我试图评论一个回复在上面的线程,但它不会让我没有足够的声誉(但会让我张贴一个答案)。
我将沿着提供的答案vivax,然后添加以下未知数据:

from typing import Mapping, Any

Mapping[str, Any] # or Mapping[Any, Any] if the keys are also unknown

字符串
您还可以通过定义自己的JSON类型来获得更多的粒度

相关问题