简体   繁体   English

用于内置类型(float、int 等)的 json_encoders

[英]pydantic `json_encoders` for builtin types (float, int, etc)

I'm having some unexpected behavior with json encoding of fields like float , int , etc. using pydantic.我在使用 pydantic 对floatint等字段进行 json 编码时遇到了一些意外行为。 Here is the documentation for json encoding, for reference.这里是json编码的文档,供参考。

As an example, this model seems to encode complex just fine, but ignores my float field.例如,这个 model 似乎可以很好地编码complex ,但忽略了我的float字段。

import pydantic as pd

class Model(pd.BaseModel):
    class Config:
        arbitrary_types_allowed=True
        json_encoders = {
            float: lambda x: 'test',
            complex: lambda x: 'test'
        }
    d1:float
    d2:complex

m = Model(d1=1.0, d2=1j)
m.json()
# '{"d1": 1.0, "d2": "test"}'

Can anyone shine light on this behavior and point me in the right direction?谁能阐明这种行为并为我指明正确的方向?

My use case is a custom encoder to detect when a float is numpy.inf and then write it to "Infinity" in json rather than the illegal default value of Infinity as encoded by the json package.我的用例是一个自定义编码器,用于检测float何时为numpy.inf ,然后将其写入 json 中的"Infinity" ,而不是json package 编码的Infinity的非法默认值。

Thanks for your help!谢谢你的帮助!

The reason behind why your custom json_encoder not working for float type is pydantic uses json.dumps() for serialization.您的自定义 json_encoder 不适用于float类型的原因是pydantic使用json.dumps()进行序列化。 If any type is serializable with json.dumps() it will not use cutom json_encoder for those types.如果任何类型可使用json.dumps()进行序列化,则不会对这些类型使用 cutom json_encoder。

And come to the complex type it's not serializable by json.dumps() that's why it's using the custom json_encoder you have provided.来到complex类型,它不能被json.dumps()序列化,这就是它使用您提供的自定义 json_encoder 的原因。

If you still want to use custom json_encoder you can use orjson as suggested by pydantic.如果您仍想使用自定义 json_encoder,您可以按照 pydantic的建议使用 orjson。

Custom JSON (de)serialisation 自定义 JSON(反)序列化

Sample Code:示例代码:

def orjson_dumps(v, *, default):
    for key, value in v.items():
        if isinstance(value, float):
            v[key] = 'test'
        elif isinstance(value, complex):
            v[key] = 'test'
    # orjson.dumps returns bytes, to match standard json.dumps we need to decode
    return orjson.dumps(v, default=default).decode()
    

class Model(BaseModel):
    class Config:
        arbitrary_types_allowed=True
        json_dumps = orjson_dumps
        json_loads = orjson.loads
    d1:float
    d2:complex

m = Model(d1=1.0, d2=1j)
m.json() # {"d1":"test","d2":"test"}

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

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