【问题标题】:Retrieve JSON string from pydantic Json type从 pydantic Json 类型中检索 JSON 字符串
【发布时间】:2021-08-16 11:38:38
【问题描述】:

我有一个如下的pydantic模型。

from pydantic import Json, BaseModel
class Foo(BaseModel):
    id: int
    bar: Json

Foo.bar 可以将 JSON 字符串解析为输入并将其存储为一个很好的字典。

foo = Foo(id=1, bar='{"foo": 2, "bar": 3}')
type(foo.bar) #outputs dict

如果我希望整个对象成为dict,我可以这样做

foo.dict()
#outputs
{'id': 1, 'bar': {'foo': 2, 'bar': 3}}

但是如何将bar 导出为 JSON 字符串,如下所示

{'id': 1, 'bar': '{"foo": 2, "bar": 3}'}

我想将 JSON 写回数据库。

【问题讨论】:

    标签: python pydantic


    【解决方案1】:

    Pydantic 作者在这里。

    如果不致电json.dumps(foo.bar),目前无法做到这一点。如果您愿意,您可以在Foo 上创建一个方法,这样会更容易使用,但需要相同的处理。

    如果性能至关重要,或者您需要与开头完全相同的 JSON 字符串(相同的空格等),您可以执行以下操作之一:

    • bar 设为字符串字段,但添加验证器以检查其是否为有效 JSON
    • 创建自定义数据类型来解析 JSON,同时保留对原始 JSON 字符串的引用

    【讨论】:

    • 感谢您的回答,性能不是超级关键。现在我使用bar 作为验证字符串。我希望foo.fields 能给我'bar': ModelField(name='bar', type=Json, required=False, default=None),这样我就可以识别Json 字段并覆盖dict() 方法并执行json.dumps(self.bar)。我认为它只是让读取和写入数据库变得更容易,而无需手动更改我所有模型中的 Json 类型。现在,当我尝试获取字段类型时,我得到了这个 'bar': ModelField(name='bar', type=Optional[Any], required=False, default=None)
    • 我会试试这个create a custom data type to parse the JSON but also keep a reference to the raw JSON string
    • 看看foo.__fields__,它会为您提供这些数据,尽管与检查一样明显。
    • 嘿,我已经用 foo.schema() 解决了这个问题,而不是 fields 作为 __fields__ 指定 Json 作为 Any。感谢这个美妙的图书馆! stackoverflow.com/a/67907251/11061699
    【解决方案2】:

    要将嵌套转换为字符串吗?

    x = {'id': 1, 'bar': str({'foo': 2, 'bar': 3})}
    

    给予

    {'id': 1, 'bar': "{'foo': 2, 'bar': 3}"}
    

    【讨论】:

    • 这是我目前的做法。我将bar 保留为字符串类型。并在pydantic之外处理json.dumpsjson.loads
    • 也许我不明白你想要什么。如果它是一个字典,你想将字典值转换为字符串吗?在这种情况下,你可以做一些字典迭代器,如果值是字典,则转换为字符串。
    • 简单地说。我正在从数据库中读取 Foo() 。并将其作为字符串存储在数据库中。在我找回它之后。我将 JSON 转换为 python 对象(现在可以在 pydantic 中完成)。但是当我尝试写入数据库时​​。字段bar 有一个python 对象而不是JSON 字符串。换一种说法。我想在 python 中使用 dict 对象并在数据库中存储和检索 JSON
    【解决方案3】:

    在我的场景中解决问题的解决方法是继承 BaseModel 并覆盖 dict 方法。

    class ExtendedModel(BaseModel):
        def dict(self, json_as_string=False, **kwargs) -> dict:
            __dict = super().dict(**kwargs)
            if json_as_string:
                for field, _ in self.schema()['properties'].items():
                    if _.get('format') == 'json-string' and field in __dict :
                        __dict[field] = json.dumps(getattr(self, field))
            return __dict
     
    

    self.__field__ 不会指定字段的类型是否实际上是 Json。它以 Any 的形式返回。所以我用了这个方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多