Marshmallow: Help to deserialize complex JSON

Created on 5 Jul 2018  路  14Comments  路  Source: marshmallow-code/marshmallow

I need to deserialize this JSON:

{
    "emails": {
        "items": [
            {
                "id": 1,
                "email": "[email protected]"
            },
            {
                "id": 2,
                "email": "[email protected]"
            }
        ]
    }
}

Into this object using Marshmallow:

{
    "emails": [
        {
            "id": 1,
            "email": "[email protected]"
        },
        {
            "id": 2,
            "email": "[email protected]"
        }
    ]
}

How can I do it?

I tried this way, which I found more intuitive, but it did not work:

class Phone(OrderedSchema):
    id = fields.Int()
    email = fields.Str()

class Contact(Schema):
    key = fields.Str()
    phones = fields.Nested(Phone, load_from='phones.list', many=True)
question

All 14 comments

What version of marshmallow are you using? Can you edit your example so that the data and the schema match?

marshmallow==2.15.3

The example is correct!
I'm trying to deserialize JSON into object (which has a structure different from the original).

I tried this way but didn't work:

phones = fields.Nested(Phone, load_from='phones.list', many=True)

Loading from a nested field name is not currently supported. #611 is a feature request for that syntax.

But there is another way to do this without using Nested field?

Create a schema for the intermediate container, then "pluck" the list value out of it into the parent schema.

class Phone(OrderedSchema):
    id = fields.Int()
    email = fields.Str()

class Phones(Schema):
    list = fields.Nested(Phone, many=True)

class Contact(Schema):
    key = fields.Str()
    phones = fields.Nested(Phones, only='list')

823 should make this a little more intuitive in v3 with a dedicated Pluck field.

I try this way:

class Item(OrderedSchema):
    id = fields.Int()

class Phone(OrderedSchema):
    items = fields.Nested(Item, many=True)

class Contact(OrderedSchema):
    key = fields.Str()
    phones = fields.Nested(Phone, only='items')

But not works:

[
    {
        "key": "1042F608-84C0-4F11-A685-61D06394EF0D",
        "phones": {
            "items": [
                {
                    "id": 1
                }
            ]
        }
    }
]

The expected result is:

[
    {
        "key": "1042F608-84C0-4F11-A685-61D06394EF0D",
        "phones": [
            {
                "id": 1
            }
        ]
    }
]

Can u help me @deckar01?

I try update to 3.0.0b12 (latest beta version) to use Pluck, but raise this error:
AttributeError: module 'marshmallow.fields' has no attribute 'Pluck'

With Pluck i try do this:

phones = fields.Pluck(Phone, 'items', many=True)

Pluck is work in progress. It is not available yet.

@lafrech but there is another way to do this without using Pluck?

@lafrech this didn't work.
See result and expected result here.
I need hide items in the expected result.

data = {
    "emails": {
        "items": [
            {
                "id": '1',
                "email": "[email protected]"
            },
            {
                "id": '2',
                "email": "[email protected]"
            }
        ]
    }
}


class Email(marshmallow.Schema):
    id = marshmallow.fields.Int()
    email = marshmallow.fields.Email()


class Emails(marshmallow.Schema):
    emails = marshmallow.fields.Nested(Email, many=True)

    @marshmallow.pre_load
    def load_emails(self, data):
        data['emails'] = data['emails']['items']
        return data


print(Emails().load(data))
# {'emails': [{'id': 1, 'email': '[email protected]'}, {'id': 2, 'email': '[email protected]'}]}

Please reopen if still stuck.

BTW, Pluck field was just released (in Marshmallow 3 beta).

Was this page helpful?
0 / 5 - 0 ratings