diff --git a/src/marshmallow/schema.py b/src/marshmallow/schema.py index ffdc3e04e..577ba7d2d 100644 --- a/src/marshmallow/schema.py +++ b/src/marshmallow/schema.py @@ -228,6 +228,7 @@ def __init__(self, meta, ordered: bool = False): self.dump_only = getattr(meta, "dump_only", ()) self.unknown = validate_unknown_parameter_value(getattr(meta, "unknown", RAISE)) self.register = getattr(meta, "register", True) + self.many = getattr(meta, "many", False) class Schema(base.SchemaABC, metaclass=SchemaMeta): @@ -344,6 +345,7 @@ class Meta: `OrderedDict`. - ``exclude``: Tuple or list of fields to exclude in the serialized result. Nested fields can be represented with dot delimiters. + - ``many``: Whether the data is a collection by default. - ``dateformat``: Default format for `Date ` fields. - ``datetimeformat``: Default format for `DateTime ` fields. - ``timeformat``: Default format for `Time ` fields. @@ -367,7 +369,7 @@ def __init__( *, only: types.StrSequenceOrSet | None = None, exclude: types.StrSequenceOrSet = (), - many: bool = False, + many: bool | None = None, context: dict | None = None, load_only: types.StrSequenceOrSet = (), dump_only: types.StrSequenceOrSet = (), @@ -381,7 +383,7 @@ def __init__( raise StringNotCollectionError('"exclude" should be a list of strings') # copy declared fields from metaclass self.declared_fields = copy.deepcopy(self._declared_fields) - self.many = many + self.many = self.opts.many if many is None else many self.only = only self.exclude: set[typing.Any] | typing.MutableSet[typing.Any] = set( self.opts.exclude diff --git a/tests/test_options.py b/tests/test_options.py index 2b052a31c..4200ab905 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -262,3 +262,19 @@ class AddFieldsChild(self.AddFieldsSchema): assert "email" in s._declared_fields.keys() assert "from" in s._declared_fields.keys() assert isinstance(s._declared_fields["from"], fields.Str) + + +class TestManyOption: + class ManySchema(Schema): + foo = fields.Str() + + class Meta: + many = True + + def test_many_by_default(self): + test = self.ManySchema() + assert test.load([{"foo": "bar"}]) == [{"foo": "bar"}] + + def test_explicit_single(self): + test = self.ManySchema(many=False) + assert test.load({"foo": "bar"}) == {"foo": "bar"}