Marshmallow: Nested schema with a list field does not abide required

Created on 4 Mar 2015  路  7Comments  路  Source: marshmallow-code/marshmallow

Have a nested schema using a list field and trying to make it required. A normal field within the same nested schema will enforce required just fine. The documentation states the list field inherits the same kwargs.

Here's a stripped down version:

class Links(Schema):
    states = fields.List(fields.String(), required=True) # Does not work
    region = fields.Integer(required=True) # Works fine

class Job(Schema):
    id = fields.Integer()
    links = fields.Nested(Links)

I've also tried putting the required kwarg at the list string field level too.

Hope I have not overlooked something. The more I dug the more it started to look like a bug. Thank you!

Most helpful comment

If i understand the problem right:

from marshmallow import Schema, fields, validate

class Links(Schema):                                                        
        states = fields.List(fields.String(), required=True, validate=validate.Length(min=1))
        region = fields.Integer(required=True)

class Job(Schema):
    id = fields.Integer()
    links = fields.Nested(Links)

Job().load({                                                                                
    "links": {                                 
        "states": [],
        "region": 1
    }                                                          
})

# UnmarshalResult(data={'links': None}, errors={'links': {'states': [u'Shorter than minimum length 1.']}})

All 7 comments

Thanks for reporting! I will look into this soon.

@morgan Can you give an example input where the required validation is not working?

@sloria Sure thing. The list is empty, flagged as required and no error is produced:

{
    "jobs": {
        "links": {
            "states": []
        }
    }
}

@morgan Thanks for clarifying. The behavior you are seeing is the expected--though perhaps not the desired--behavior. required=True validates the _presence_ of the field in the input dictionary; it does not validate whether the input list is empty or not.

Inconsistency in validating empty values was noted for string fields in #76 and is addressed in 2.0.0 (see http://marshmallow.readthedocs.org/en/dev/upgrading.html#deserializing-empty-values-allow-none-and-allow-blank).

I think it would make sense to add an allow_empty param to List as well.

If i understand the problem right:

from marshmallow import Schema, fields, validate

class Links(Schema):                                                        
        states = fields.List(fields.String(), required=True, validate=validate.Length(min=1))
        region = fields.Integer(required=True)

class Job(Schema):
    id = fields.Integer()
    links = fields.Nested(Links)

Job().load({                                                                                
    "links": {                                 
        "states": [],
        "region": 1
    }                                                          
})

# UnmarshalResult(data={'links': None}, errors={'links': {'states': [u'Shorter than minimum length 1.']}})

Thanks @rastikerdar -- that is the right approach; We probably don't need to introduce the allow_empty parameter, as you can achieve the same validation using validate.Length

not_empty = validate.Length(min=1, error='Field cannot be empty.')

states = fields.List(fields.Str(), required=True, validate=not_empty)

@morgan Does that meet your use case?

@sloria I see. The required=True is indicating simply that the key needs to be set but doesn't care if the value(s) are empty.

Thank you for providing more clarity!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ambye85 picture ambye85  路  4Comments

k0nsta picture k0nsta  路  4Comments

j4k0bk picture j4k0bk  路  3Comments

tadams42 picture tadams42  路  3Comments

jayennis22 picture jayennis22  路  4Comments