简体   繁体   English

Python 数据类循环解析与棉花糖

[英]Python dataclasses circular parsing with marshmallow

I'm working with a JSON data structure and am trying to represent it as a dataclass.我正在使用 JSON 数据结构,并试图将其表示为数据类。 The data structure is (partly) circular and I want the nested data structures to be neatly represented as dataclasses as well.数据结构(部分)是循环的,我希望嵌套的数据结构也可以整齐地表示为数据类。

I am having some trouble getting the dataclasses to parse correctly.我在让数据类正确解析时遇到了一些麻烦。 See the simplified example below:请参见下面的简化示例:

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

Below is a printout of the object returned after calling from_dict with some sample data.下面是使用一些示例数据调用from_dict后返回的 object 的打印输出。 Notice that the nested object (indicated with the arrow) is not parsed as a dataclass correctly.请注意,嵌套的 object(用箭头表示)未正确解析为数据类。

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

Am I declaring the type hint for the type field incorrectly?我是否错误地声明了type字段的类型提示?

I'm using Python 3.9 with dataclasses_json==0.5.2 and marshmallow==3.11.1 .我正在使用Python 3.9dataclasses_json==0.5.2marshmallow==3.11.1

I found that the problem was related to dataclasses_json not decoding my elements correctly when they are in a list.我发现问题与dataclasses_json在列表中未正确解码我的元素有关。 Having mixed types in a list causes the decoder to return a list of basic string s and dict s, without transforming them to instances of SchemaType and SchemaTypeName .在列表中混合类型会导致解码器返回基本stringdict的列表,而不会将它们转换为SchemaTypeSchemaTypeName的实例。

However, dataclasses_json allows you to configure a custom decoder function for any particular field.但是, dataclasses_json允许您为任何特定字段配置自定义解码器 function。 This is done by importing the config function from dataclasses_json and providing it as the metadata keyword argument for field .这是通过从 dataclasses_json 导入config dataclasses_json并将其作为fieldmetadata关键字参数来完成的。 Next, include the decoder function as the decoder keyword argument for config .接下来,包含解码器 function 作为configdecoder关键字参数。

Please see the updated example below.请参阅下面的更新示例。 Using the schemaTypeDecoder function, I am able to transform my data to the correct types.使用schemaTypeDecoder function,我能够将我的数据转换为正确的类型。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM