Currently (as of version 3.13.0), this is how data_key is handled (source):
...
key = field_obj.data_key if field_obj.data_key is not None else attr_name
ret[key] = value
return ret
...
So if you try to specify a e.g., tuple as data_key (with a list will not work since it's not hashable), the whole tuple will constitute the key of the dictionary ret (see above). Therefore, it will not work with single strings.
A workaround could be to use the pre_load decorator, e.g.:
from marshmallow import Schema, fields, pre_load, ValidationError
class PersonSchema(Schema):
name = fields.String()
age = fields.Integer()
@pre_load
def process_data_key(self, data, **kwargs):
names = [name for name in data.keys()
if name in ("name", "user_name", "UserName", "userName")]
if len(names) > 1:
raise ValidationError('Multiple values for field "name".')
if names: # check if any name was included at all
data["name"] = data.pop(names[0])
return data
s = PersonSchema()
data = {"name": "Mike", "age": "32"}
result = s.load(data)
print(result) # {'name': 'Mike', 'age': 32}
data = {"user_name": "Mike", "age": "32"}
result = s.load(data)
print(result) # {'name': 'Mike', 'age': 32}
data = {"UserName": "Mike", "age": "32"}
result = s.load(data)
print(result) # {'name': 'Mike', 'age': 32}
data = {"name": "Mike", "UserName": "Mike", "age": "32"}
try:
result = s.load(data)
except ValidationError as err:
print(err.messages) # {'_schema': ['Multiple values for field "name".']}
data = {"age": "32"}
result = s.load(data)
print(result) # {'age': 32}
The idea above is to "map" all the different variations of name (i.e., user_name, UserName, etc.) to name.