Automatic dictionary key resolution with nested schemas using Marshmallow

2024/9/27 15:25:58

I have a Marshmallow schema where an objects use a key to refer to an object that is defined in a dictionary in another part of the structure. I want to have the key automatically resolved when deserializing the object. How can I achieve this effect in Marshmallow in an idiomatic manner?

The workaround for now is to resolve all of the references manually, but this seems clunky, since the declarative nature of Marshmallow should be able to do it for us automatically.

Note that Marshmallow-SQLAlchemy supports this kind of (de-)serialization when columns are declared as relationships" which do this automatically for us, but I want to do it with JSON data.

Here is an example of what I want to achieve, with fields.Relationship being something that does not exist yet:

class UserSchema(Schema):name = fields.String()email = fields.Email()friends = fields.Relationship('self', path="AddressBook.contacts", many=True)class AddressBookSchema(Schema):contacts = nested.Dict(keys=fields.String(), values=fields.Nested(UserSchema))# ... create ``user`` ...
serialized_data = AddressBookSchema().dump(user)
pprint(serialized_data)
# "contacts": {
#   "Steve": {
#     "name": "Steve",
#     "email": "[email protected]",
#     "friends": ["Mike"]
#   },
#   "Mike": {
#     "name": "Mike",
#     "email": "[email protected]",
#     "friends": []
# }deserialized_data = UserSchema().load(result)
pprint(deserialized_data)
# "contacts": {
#   "Steve": {
#     "name": "Steve",
#     "email": "[email protected]",
#     "friends": [ {"name": "Mike", "email": "[email protected]"]
#   },
#   "Mike": {
#     "name": "Mike",
#     "email": "[email protected]",
#     "friends": []
# }

I have also filed an issue on the Marshmallow Github repository.

Answer

why not simply transfer the intermediate data with a post_load hook:

class UserSchema(Schema):name = fields.String()email = fields.Email()friends = fields.List(fields.String())class AddressBookSchema(Schema):contacts = fields.Dict(keys=fields.String(), values=fields.Nested(UserSchema))@post_loaddef trans_friends(self, item):for name in item['contacts']:item['contacts'][name]['friends'] = [item['contacts'][n] for n in item['contacts'][name]['friends']]data = """
{"contacts": {"Steve": {"name": "Steve","email": "[email protected]","friends": ["Mike"]},"Mike": {"name": "Mike","email": "[email protected]","friends": []}}
}
"""deserialized_data = AddressBookSchema().loads(data)
pprint(deserialized_data)

yields:

UnmarshalResult(data={'contacts': {'Steve': {'name': 'Steve', 'email': '[email protected]', 'friends': [{'name': 'Mike', 'email': '[email protected]', 'friends': []}]}, 'Mike': {'name': 'Mike', 'email': '[email protected]', 'friends': []}}}, errors={})
https://en.xdnf.cn/q/71443.html

Related Q&A

Type hinting for Django Model subclass

I have helper function for Django views that looks like this (code below). It returns None or single object that matches given query (e.g. pk=1). from typing import Type, Optionalfrom django.db.models …

How to diff the two files using Python Generator

I have one file of 100GB having 1 to 1000000000000 separated by new line. In this some lines are missing like 5, 11, 19919 etc. My Ram size is 8GB.How to find the missing elements.My idea take another …

How to resolve: attempted relative import with no known parent package [duplicate]

This question already has answers here:Attempted relative import with no known parent package [duplicate](4 answers)Closed 2 years ago.I have a bare bones project structure with mostly empty python fil…

How to create a figure of subplots of grouped bar charts in python

I want to combine multiple grouped bar charts into one figure, as the image below shows. grouped bar charts in a single figure import matplotlib import matplotlib.pyplot as plt import numpy as nplabels…

Python Pillow: Make image progressive before sending to 3rd party server

I have an image that I am uploading using Django Forms, and its available in the variable as InMemoryFile What I want to do is to make it progressive.Code to make an image a progressiveimg = Image.open…

Python - Should one start a new project directly in Python 3.x?

What Python version can you please recommend for a long-term (years) project? Should one use 2.6+ or 3.x is already stable? (only standard libraries are required)UPDATE: according to the answers belo…

Produce random wavefunction

I need to produce a random curve in matplotlib.My x values are from say 1 to 1000 for example. I dont want to generate scattered random y values, I need a smooth curve. Like some kind of very distorted…

How to reference groupby index when using apply, transform, agg - Python Pandas?

To be concrete, say we have two DataFrames:df1:date A 0 12/1/14 3 1 12/1/14 1 2 12/3/14 2 3 12/3/14 3 4 12/3/14 4 5 12/6/14 5df2:B 12/1/14 10 12/2/14 20 12/3/14 10 12/4/14 30 12/5/14 10 …

Google AppEngine Endpoints Error: Fetching service config failed (status code 404)

I am implementing the steps in the Quickstart.I did notice another question on this. I double checked that env_variables section in app.yaml has the right values for ENDPOINTS_SERVICE_NAME and ENDPOIN…

How to unload a .NET assembly reference in IronPython

After loading a reference to an assembly with something like:import clr clr.AddRferenceToFileAndPath(rC:\foo.dll)How can I unload the assembly again?Why would anyone ever want to do this? Because Im …