如何使棉花糖在序列化时引发 AttributeErrors

How to make marshmallow raise AttributeErrors on serialization

当数据缺少属性时,如何让 marshmallow make 引发异常?

考虑以下示例:

In [8]: import marshmallow

In [9]: class Foo(marshmallow.Schema):
   ...:     bar = marshmallow.fields.Str(required=True)
   ...:

In [10]: class Bar:
    ...:     pass
    ...:

In [11]: bar = Bar()

In [12]: Foo().dumps(bar)
Out[12]: MarshalResult(data='{}', errors={})

In [13]: bar.bar
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-13-6901e83d9f0c> in <module>()
----> 1 bar.bar

AttributeError: 'Bar' object has no attribute 'bar'

更糟糕的是:

In [14]: foo.loads(foo.dumps(bar).data)
Out[14]: UnmarshalResult(data={}, errors={'bar': ['Missing data for required field.']})

issue 中的以下引述解释了您在问题的第一部分中描述的行为。

This is by design. Primarily for performance reasons, validation only happens on deserialization (load and validate). The data passed to dump is assumed to be valid.

如果您需要验证,例如,您将显式调用 validate()。从你的例子:

In [10]: foo.validate(foo.dump(foo).data)
---------------------------------------------------------------------------
ValidationError                           Traceback (most recent call last)
<ipython-input-40-4dfb5988e928> in <module>()
----> 1 foo.validate(foo.dump(foo).data)

...

ValidationError: {'bar': ['Missing data for required field.']}

关于反序列化期间缺少验证,对于您使用的 marshmallow 版本,您必须明确声明架构为 'strict' 以便自动进行验证。在您的示例中,这可以通过以下方式完成:

In [22]: class Foo(marshmallow.Schema):
    ...:     bar = marshmallow.fields.Str(required=True)
    ...:     class Meta:
    ...:         strict = True

In [23]: foo = Foo()

In [24]: foo.loads(foo.dumps(bar).data)
---------------------------------------------------------------------------
...
ValidationError: {'bar': ['Missing data for required field.']}

Issue 598 中所述,此行为已更改,marshamallow 的最新版本默认为此 'strict' 行为;它还删除了 MarshalResult/UnmarshalResult 包装器。