question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Schema deserialisation with defined session and nested field throws an exception

See original GitHub issue

Not sure if this is intended functionality, however the code below throws ValueError: Deserialization requires a session when trying to load data into a nested object.

I would expect passing a session would propagate to nested fields, however this doesn’t seem to be the case. Is this by design?

If i remove followup (the nested field) from the only= property, the data loads fine from the non-nested field.


class FollowUp(ModelSchema):
    reasonCode =fields.String(attribute='reason_code')
    comment = fields.String()

class Occurence(ModelSchema):
    #... other fields before ...
    followup = fields.Nested(FollowUp())
    status = fields.String()

# Inside my request handler:
obj = DBOccurence.query.get_or_404(occ_id)
res = Occurence(only=['status', 'followup']).load(
            request.json,
            instance=obj,
            session=current_app.db.session
        )

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:3
  • Comments:14 (4 by maintainers)

github_iconTop GitHub Comments

5reactions
MattF-NSIDCcommented, Apr 29, 2019

I managed to implement a fix that builds upon the one linked in the comment above, making it general-purpose (you don’t need to know the names of your nested fields to use this):

class BaseModelSchema(ModelSchema):
    OPTIONS_CLASS = BaseOpts

    @mm.pre_load
    def set_nested_session(self, data):
        """Allow nested schemas to use the parent schema's session. This is a
        longstanding bug with marshmallow-sqlalchemy.

        https://github.com/marshmallow-code/marshmallow-sqlalchemy/issues/67
        https://github.com/marshmallow-code/marshmallow/issues/658#issuecomment-328369199
        """
        nested_fields = {k: v for k, v in self.fields.items() if type(v) == mm.fields.Nested}
        for field in nested_fields.values():
            field.schema.session = self.session
5reactions
YKdvdcommented, Nov 14, 2016

It looks like even if you specify “sqla_session” for the TopLevel schema definition, it doesn’t get passed along to the Nested schemas, so Nested() is broken completely except where the nested schema itself specifies a “sqla_session” in its definition?
I took a quick look at the code (schema.py), and it would seem that there is no way that the session could have been intended to propagate to nested schemas? The constructor would have to attach the “session” parm it was passed to any nested mmsqla.ModelSchema fields after the super() call constructed the parent schema. And load() would have to something similar as a one-time thing. I didn’t see anything that looked like it could do this. Also, ModelSchema keeps a “session” attribute which gets set by init() and load(). But load() looks like it doesn’t preserve the existing value? So if you had something like this, the second call would wipe out the schema specified in the constructor, and future load() calls will use the last session explicitly passed to load():

#permSession and tempSession are a couple of sqlAlchemy sessions
class MySchema(ModelSchema):
   ...
schema = MySchema(session=permSession)   # always use permSession unless overridden by load()
result = schema.load(data)   # will use permSession
result = schema.load(data, session=tempSession)  # will use tempSession
result = schema.load(data)  # should use permSession, but previous load has set schema.session to tempSession but never restored it to permSession.

I haven’t tested this, but scanning the code seems to suggest that’s what would happen.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SQLAlchemyAutoSchema Nested Deserialization
So you create your own Nested field (I just copied the code from marshmallow-sqlalchemy) at the top of schemy.py and overwrite the session....
Read more >
Apache Kafka Reference Guide - Quarkus
By default, it deduces the serializer from the key deserializer. ... Conversely, if the processing throws an exception, all messages are nacked, ...
Read more >
Simple 2.7.1 - Simple XML Serialization
This page provides a tutorial that will prepare users for using XML serialization. Before this tutorial is attempted it is advisable to have...
Read more >
Pipes | NestJS - A progressive Node.js framework
Hint Pipes run inside the exceptions zone. This means that when a Pipe throws an exception it is handled by the exceptions layer...
Read more >
Jackson: java.util.LinkedHashMap cannot be cast to X
LinkedHashMap cannot be cast to X" exception occurs and how to solve ... Second, when Jackson attempts to deserialize an object in JSON...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found