Python 数据类用棉花糖进行循环解析
Python dataclasses circular parsing with marshmallow
我正在使用 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.9
与 dataclasses_json==0.5.2
和 marshmallow==3.11.1
一起使用。
我发现问题与 dataclasses_json
在列表中时未正确解码我的元素有关。在列表中混合类型会导致解码器 return 基本 string
和 dict
的列表,而不会将它们转换为 SchemaType
和 SchemaTypeName
的实例.
但是,dataclasses_json
允许您为任何特定字段配置自定义解码器函数。这是通过从 dataclasses_json
导入 config
函数并将其作为 field
的 metadata
关键字参数提供来完成的。接下来,将解码器函数包含为 config
.
的 decoder
关键字参数
请参阅下面的更新示例。使用 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
我正在使用 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.9
与 dataclasses_json==0.5.2
和 marshmallow==3.11.1
一起使用。
我发现问题与 dataclasses_json
在列表中时未正确解码我的元素有关。在列表中混合类型会导致解码器 return 基本 string
和 dict
的列表,而不会将它们转换为 SchemaType
和 SchemaTypeName
的实例.
但是,dataclasses_json
允许您为任何特定字段配置自定义解码器函数。这是通过从 dataclasses_json
导入 config
函数并将其作为 field
的 metadata
关键字参数提供来完成的。接下来,将解码器函数包含为 config
.
decoder
关键字参数
请参阅下面的更新示例。使用 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