-
-
Notifications
You must be signed in to change notification settings - Fork 639
Open
Description
Link: marshmallow.readthedocs.io/en/stable/nesting.html#nesting-a-schema-within-itself
class UserSchema(Schema):
name = fields.String()
email = fields.Email()
# Use the 'exclude' argument to avoid infinite recursion
employer = fields.Nested(lambda: UserSchema(exclude=("employer",)))
friends = fields.List(fields.Nested(lambda: UserSchema()))
user = User("Steve", "steve@example.com")
user.friends.append(User("Mike", "mike@example.com"))
user.friends.append(User("Joe", "joe@example.com"))
user.employer = User("Dirk", "dirk@example.com")
result = UserSchema().dump(user)
pprint(result, indent=2)
# {
# "name": "Steve",
# "email": "steve@example.com",
# "friends": [
# {
# "name": "Mike",
# "email": "mike@example.com",
# "friends": [],
# "employer": null
# },
# {
# "name": "Joe",
# "email": "joe@example.com",
# "friends": [],
# "employer": null
# }
# ],
# "employer": {
# "name": "Dirk",
# "email": "dirk@example.com",
# "friends": []
# }
# }
While the example usage itself doesn't run into infinite recursion, the schema is prone to it:
user = User("Steve", "steve@example.com")
dirk = User("Dirk", "dirk@example.com")
user.employer = dirk
dirk.friends.append(user)
result = UserSchema().dump(user)
pprint(result, indent=2)
user = User("Steve", "steve@example.com")
mike = User("Mike", "mike@example.com")
joe = User("Joe", "joe@example.com")
user.friends.append(mike)
mike.friends.append(user)
user.friends.append(joe)
joe.friends.append(user)
dirk = User("Dirk", "dirk@example.com")
user.employer = dirk
dirk.friends.append(user)
result = UserSchema().dump(user)
pprint(result, indent=2)
Possible solutions:
- Make either relationship a leaf node
class UserSchema(Schema):
name = fields.String()
email = fields.Email()
# Use the 'exclude' argument to avoid infinite recursion
employer = fields.Nested(lambda: UserSchema(exclude=("employer", "friends")))
friends = fields.List(fields.Nested(lambda: UserSchema(exclude=("friends",))))
class UserSchema(Schema):
name = fields.String()
email = fields.Email()
# Use the 'exclude' argument to avoid infinite recursion
employer = fields.Nested(lambda: UserSchema(exclude=("employer",)))
friends = fields.List(fields.Nested(lambda: UserSchema(exclude=("employer", "friends"))))
- Make both relationships leaf nodes
class UserSchema(Schema):
name = fields.String()
email = fields.Email()
# Use the 'exclude' argument to avoid infinite recursion
employer = fields.Nested(lambda: UserSchema(exclude=("employer", "friends")))
friends = fields.List(fields.Nested(lambda: UserSchema(exclude=("employer", "friends"))))
- Use a single relationship
class UserSchema(Schema):
name = fields.String()
email = fields.Email()
# Use the 'exclude' argument to avoid infinite recursion
friends = fields.List(fields.Nested(lambda: UserSchema(exclude=("friends",))))
Happy to contribute if accepted!
Metadata
Metadata
Assignees
Labels
No labels