Validates that all values present in a list input is unique, ie. didn't occur more than once.
could be subclass of List or another solution is to use unique=True keyword argument to List field class
and implement code bellow directly into List field
from collections import Counter
from marshmallow.validate import ValidationError
class UniqueList(fields.List):
default_error_messages = {'unique': 'Values not unique.'}
def _deserialize(self, value, attr, data, **kwargs) -> typing.List[typing.Any]:
try:
result = super()._deserialize(value, attr, data, **kwargs)
except ValidationError as error:
raise error
unique_result = set(result)
if len(result) > len(unique_result):
counts = Counter(result)
unique = list(dict(list(filter(lambda i: i[1] == 1, Counter(result).items()))).keys())
msg = self.error_messages['unique']
raise ValidationError(msg, valid_data=unique)
return result
Not entirely opposed to adding this, but it's a bit tricky to handle both hashable and non-hashable types. Also, it's pretty easy to define this in userland:
def validate_uniqueness(value: Sequence):
if len(set(value)) < len(value):
raise ValidationError("Values must be unique.")
class MySchema(Schema):
my_field = fields.List(fields.Str(), validate=validate_uniqueness)
I'd recommend doing that for now.
Closing for now, as we don't have plans to add this to core in the near future and the use case can easily be met in userland (see my comment above)
Most helpful comment
Not entirely opposed to adding this, but it's a bit tricky to handle both hashable and non-hashable types. Also, it's pretty easy to define this in userland:
I'd recommend doing that for now.