New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Return deserialized data when strict=True #598
Comments
I am in favor of strict=True by default, but I think the API for load() returning different KINDS of data depending on configuration might be confusing. |
I think it's better if methods always return the same "kind" or "shape" of data. However, here's an alternative... What about a second method such as .loaddata() which only retrieves the data and ignores the errors? This way there's a shorthand for people who don't care about the errors. Obviously also the corresponding .loadsdata(). I suppose this isn't much shorter though than .load().data... maybe your current API here is plenty good! |
@douglas-treadwell I vote not to do that. Once Marshmallow goes this route, there are plenty of option combinations to introduce as a new methods: @sloria I would rather opt to deprecate |
@maximkulkin I agree and withdraw my suggestion about loaddata(). It's perfectly fine to do load().data. |
I like @maximkulkin 's suggestion. So we would
|
One use case that would be missed if we deprecate from marshmallow import Schema, fields
class MySchema(Schema):
always_valid = fields.Field()
always_invalid = fields.Field(validate=[lambda val: False])
sch = MySchema()
data = {'always_valid': 42, 'always_invalid': 24}
res = sch.load(data)
# Partially valid data
print(res.data) # => {'always_valid': 42}
# Error messages
print(res.errors) # => {'always_invalid': ['Invalid value.']} A simple solution would be to store partially valid data on try:
data = schema.load(data)
except ValidationError as err:
# Partially valid data
valid_data = err.valid_data
# Error messages
errors = err.messages
# Raw input data
raw_data = err.data |
I've gone ahead and implemented the |
To anyone interested in this, I've been working on it in #711. I believe it is almost ready. The docs still need to be updated. I'm unsure about how Currently, by default, I kept current behaviour: it will raise def load(self, data, many=None, partial=None):
return self._do_load(data, many, partial=partial, postprocess=True)
def validate(self, data, many=None, partial=None):
self._do_load(data, many, partial=partial, postprocess=False) Maybe it would be more useful if it caught You could do if MySchema().validate(input_data) or errors = MySchema().validate(input_data) For instance, you'd do: errors = MySchema().validate(input_data)
if errors:
... # Manage errors
else:
... # Proceed rather than try:
MySchema().validate(input_data)
except ValidationError as exc:
errors = exc.errors
... # Manage errors
else:
... # Proceed I favor try/except logics when the "normal" workflow does not trigger an exception, but if the user explicitly calls |
I agree; it's intuitive for |
Great. Done. |
Status quo
load
currently returns a namedtuple (UnmarshalResult
) containing both the deserialized data and error messages.Proposed API
When
strict=True
, return only the deserialized data. Messages can already be accessed fromValidationError.messages
.The text was updated successfully, but these errors were encountered: