【问题标题】:Python dataclasses circular parsing with marshmallowPython数据类循环解析与棉花糖
【发布时间】:2022-01-17 02:05:17
【问题描述】:

我正在使用 JSON 数据结构并尝试将其表示为数据类。数据结构(部分)是循环的,我希望嵌套的数据结构也可以整齐地表示为数据类。

我在正确解析数据类时遇到了一些问题。请参阅下面的简化示例:

from typing import List, Optional, Union


class SchemaTypeName(Enum):
    LONG = "long"
    NULL = "null",
    RECORD = "record"
    STRING = "string"


@dataclass_json
@dataclass
class SchemaType():

    type: Union[
        SchemaTypeName,
        'SchemaType',
        List[
            Union[
                SchemaTypeName,
                'SchemaType'
            ]
        ]
    ]

    fields: Optional[List['SchemaType']] = None
    name: Optional[str] = None

下面是调用from_dict 后返回的对象的打印输出,其中包含一些示例数据。请注意,嵌套对象(用箭头表示)未正确解析为数据类。

SchemaType(
    type=[
        'null', 
------> {
            'fields': [
                {'name': 'id', 'type': 'string'}, 
                {'name': 'date', 'type': ['null', 'long']}, 
                {'name': 'name', 'type': ['null', 'string']}
            ],
            'type': 'record'
        }
    ]
)

我是否错误地声明了 type 字段的类型提示?

我将Python 3.9dataclasses_json==0.5.2marshmallow==3.11.1 一起使用。

【问题讨论】:

  • 嗯,您对 dataclass-json 库的工作方式有一些假设错误:1) 构造函数或 __init__ 方法不会自动替换,因此验证和数据转换将不起作用方式正常。我不明白的是,您将需要使用 from_dict 之类的辅助方法。 2) 你不需要同时使用@dataclass_json 装饰器和DataClassJsonMixin 子类;至少从我的理解来看,两者都使用是多余的。
  • 正确,我在单元测试中使用了from_dict,该单元测试产生了我在问题中包含的打印输出。我使用装饰器来传递示例中遗漏的一些附加参数。 DataClassJsonMixin 帮助 mypy 接受额外的方法,例如 from_dict,它不会接受那些只有装饰器的方法。
  • 感谢您的反馈,我已经相应地澄清了问题。
  • 嗯,您确定type 的最外层遇到的值将始终是SchemaType 或SchemaTypeName,并且它的所有后续值(例如嵌套在fields 中)只会是SchemaTypeName?如果是这样,可能有一个简单的解决方案。
  • fields 内只能是SchemaType 对象的列表。在type 中可以存在SchemaTypeNameSchemeTypeList,这两种类型都可以混合使用。我认为这种混合在解析步骤中造成了困难。

标签: python marshmallow python-dataclasses


【解决方案1】:

我发现问题与dataclasses_json 在列表中未正确解码我的元素有关。列表中有混合类型会导致解码器返回基本strings 和dicts 的列表,而不会将它们转换为SchemaTypeSchemaTypeName 的实例。

但是,dataclasses_json 允许您为任何特定字段配置自定义解码器功能。这是通过从dataclasses_json 导入config 函数并将其作为fieldmetadata 关键字参数提供的。接下来,将解码器函数作为configdecoder 关键字参数。

请参阅下面的更新示例。使用schemaTypeDecoder 函数,我能够将我的数据转换为正确的类型。

from dataclasses import field
from dataclasses_json import config

class SchemaTypeName(Enum):
    ARRAY = "array"
    LONG = "long"
    NULL = "null"
    OBJECT = "object"
    RECORD = "record"
    STRING = "string"


def schemaTypeDecoder(data: Union[str, dict, List[Union[str, dict]]]):

    def transform(schemaType: Union[str, dict]):
        if isinstance(schemaType, str):
            return SchemaTypeName(schemaType)
        else:
            return SchemaType.from_dict(schemaType)

    if isinstance(data, list):
        return [transform(schemaType) for schemaType in data]
    else:
        return transform(data)


@dataclass_json()
@dataclass
class SchemaType():
    type: Union[
        SchemaTypeName,
        'SchemaType',
        List[
            Union[
                SchemaTypeName,
                'SchemaType'
            ]
        ]
    ] = field(
        metadata=config(
            decoder=schemaTypeDecoder
        )
    )

    fields: Optional[List['SchemaType']] = None
    name: Optional[str] = None

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2018-06-15
    • 2018-09-19
    • 2017-02-02
    相关资源
    最近更新 更多