嵌套数据类的Json序列化

14

我需要进一步回答有关在嵌套结构中使用@dataclass进行JSON序列化的问题,该问题来自Make the Python json encoder support Python's new dataclasses

请考虑以下情况:

import json
from attr import dataclass
from dataclasses_json import dataclass_json
@dataclass
@dataclass_json
class Prod:
    id: int
    name: str
    price: float

prods = [Prod(1,'A',25.3),Prod(2,'B',79.95)]
pjson = json.dumps(prods)

这给我们带来了:

TypeError: Object of type Prod is not JSON serializable
请注意,上述内容包含其中一个答案https://dev59.com/qlUK5IYBdhLWcg3wySbB#59688140。它通过dataclass_json装饰器声称支持嵌套情况。显然,实际上并不起作用。
我还尝试了另一个答案https://dev59.com/qlUK5IYBdhLWcg3wySbB#51286749
class EnhancedJSONEncoder(json.JSONEncoder):
        def default(s, o):
            if dataclasses.is_dataclass(o):
                return dataclasses.asdict(o)
            return super().default(o)

我为此创建了一个帮助方法:

def jdump(s,foo):
    return json.dumps(foo, cls=s.c.EnhancedJSONEncoder)

但使用那种方法也没有影响(错误)结果。还有其他提示吗?

3个回答

11
你可以使用 pydantic 库。从文档中的示例了解更多信息。
from pydantic import BaseModel


class BarModel(BaseModel):
    whatever: int


class FooBarModel(BaseModel):
    banana: float
    foo: str
    bar: BarModel


m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': 123})

# returns a dictionary:
print(m.dict())
"""
{
    'banana': 3.14,
    'foo': 'hello',
    'bar': {'whatever': 123},
}
"""
print(m.dict(include={'foo', 'bar'}))
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(m.dict(exclude={'foo', 'bar'}))
#> {'banana': 3.14}

Nikita给了个很棒的答案,完美地解决了问题。现在拥有Pydantic以后,不确定还有哪些情景需要使用dataclasses。 - Edward Gaere

4

实际上这并不是一个直接的答案,而更像是一个合理的解决方案,适用于不需要(或不希望)可变性的情况。基于 typingNamedTuple 看起来和感觉相当类似,很可能是 dataclass 的灵感来源。如果需要序列化,它可能是目前最好的替代方案。

from typing import NamedTuple

class Prod(NamedTuple):
    id: str
    name: str
    price: str

我制作了一个可以替换基于dataclassProd类的东西,它能够正常工作。


2
import json
from dataclasses import dataclass, asdict


@dataclass
class Prod:
    id: int
    name: str
    price: float


prods = [asdict(Prod(1, 'A', 25.3)), asdict(Prod(2, 'B', 79.95))]
pjson = json.dumps(prods)
print(pjson)
# [{"id": 1, "name": "A", "price": 25.3}, {"id": 2, "name": "B", "price": 79.95}]

1
序列化是在dict上进行的,而不是在@dataclass本身上进行的。考虑反序列化:它需要理解如何将字典还原为数据类。 - WestCoastProjects
看看这个:https://github.com/EvgeniyBurdin/validated_dc
也许会有帮助 :)
- Evgeniy_Burdin
那是一个不错的链接! - WestCoastProjects

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接