简体   繁体   English

Json 嵌套数据类的序列化

[英]Json serialization of nested dataclasses

I would need to take the question about json serialization of @dataclass from Make the Python json encoder support Python's new dataclasses a bit further: consider when they are in a nested structure.我需要从Make the Python json 编码器进一步支持 Python 的新数据类中进一步考虑有关json serialization of @dataclass问题:考虑它们何时处于嵌套结构中。

Consider:考虑:

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)

That gives us:这给了我们:

TypeError: Object of type Prod is not JSON serializable

Note the above does incorporate one of the answers https://stackoverflow.com/a/59688140/1056563 .请注意,上面确实包含了答案之一 https://stackoverflow.com/a/59688140/1056563 It claims to support the nested case via the dataclass_json decorator.它声称通过dataclass_json装饰器支持嵌套案例。 Apparently that does not actually work.显然这实际上不起作用。

I also tried another of the answers https://stackoverflow.com/a/51286749/1056563 :我还尝试了另一个答案https://stackoverflow.com/a/51286749/1056563

class EnhancedJSONEncoder(json.JSONEncoder):
        def default(s, o):
            if dataclasses.is_dataclass(o):
                return dataclasses.asdict(o)
            return super().default(o)

And I created a helper method for it:我为它创建了一个辅助方法:

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

But using that method also did not effect the (error) result.但是使用该方法也不会影响(错误)结果。 Any further tips?任何进一步的提示?

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}]

You can use a pydantic library.您可以使用pydantic库。 From the example in documentation文档中的示例

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}

This is actually not a direct answer but more of a reasonable workaround for cases where mutability is not needed (or desirable).这实际上不是一个直接的答案,而是对于不需要(或不需要)可变性的情况的更合理的解决方法。 The typing based NamedTuple looks and feels quite similar and is probably the inspiration behind the dataclass .基于typingNamedTuple看起来和感觉都非常相似,并且可能是dataclass背后的灵感。 If serialization were needed it is likely presently the best alternative.如果需要序列化,它可能是目前最好的选择。

from typing import NamedTuple

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

I made that as a drop-in replacement for the dataclass based Prod class and it works.我把它作为基于数据类的Prod dataclass的替代品,它可以工作。

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

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