用于内置类型(float、int 等)的 pydantic `json_encoders`
pydantic `json_encoders` for builtin types (float, int, etc)
我在使用 pydantic 对 float
、int
等字段进行 json 编码时遇到一些意外行为。这里是documentation对json的编码,供参考。
例如,这个模型似乎编码 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"}'
任何人都可以阐明这种行为并为我指明正确的方向吗?
我的用例是一个自定义编码器,用于检测 float
何时为 numpy.inf
,然后将其写入 json 中的 "Infinity"
而不是非法默认值Infinity
由 json
包编码。
感谢您的帮助!
您的自定义 json_encoder 不适用于 float
类型的原因是 pydantic 使用 json.dumps()
进行序列化。
如果任何类型可以使用 json.dumps()
序列化,则不会对这些类型使用 cutom json_encoder。
然后来到 complex
类型,它不能被 json.dumps()
序列化,这就是它使用您提供的自定义 json_encoder 的原因。
如果您仍想使用自定义 json_encoder,您可以按照 pydantic 的建议使用 orjson。
示例代码:
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"}
我在使用 pydantic 对 float
、int
等字段进行 json 编码时遇到一些意外行为。这里是documentation对json的编码,供参考。
例如,这个模型似乎编码 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"}'
任何人都可以阐明这种行为并为我指明正确的方向吗?
我的用例是一个自定义编码器,用于检测 float
何时为 numpy.inf
,然后将其写入 json 中的 "Infinity"
而不是非法默认值Infinity
由 json
包编码。
感谢您的帮助!
您的自定义 json_encoder 不适用于 float
类型的原因是 pydantic 使用 json.dumps()
进行序列化。
如果任何类型可以使用 json.dumps()
序列化,则不会对这些类型使用 cutom json_encoder。
然后来到 complex
类型,它不能被 json.dumps()
序列化,这就是它使用您提供的自定义 json_encoder 的原因。
如果您仍想使用自定义 json_encoder,您可以按照 pydantic 的建议使用 orjson。
示例代码:
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"}