Search code examples
pythonmarshmallow

ordered = True not respected. python + marshmallow + Flask


it's me again, now with a marshmallow question, I have the following structure:

route.py

@models.response(ParentSchema())
def get(args, model_id):

    return {"response": {"a": [{"data": "a"}], "b": [{"data": "a"}], "c": [{"data": "a"}], "d": [{"data": "a"}]}}

then this is my schemas file schema.py

class SubChildSchema(Schema):
    data = fields.Str(description="Model's name")


class ChildSchema(Schema):

    class Meta:
        ordered = True

    a = fields.Nested(SubChildSchema, many=True)
    b = fields.Nested(SubChildSchema, many=True)
    c = fields.Nested(SubChildSchema, many=True)
    d = fields.Nested(SubChildSchema, many=True)


class ParentSchema(Schema):
    response = fields.Nested(ChildSchema)

it suppose that in the response I should get a sorted response like:

{
    "response": {
        "a": [
            {
                "data": "a"
            }
        ],
        "b": [
            {
                "data": "a"
            }
        ],
        "c": [
            {
                "data": "a"
            }
        ],
        "d": [
            {
                "data": "a"
            }
        ]
    }
}

but instead of that I am receiving

{
    "response": {
        "b": [
            {
                "data": "a"
            }
        ],
        "c": [
            {
                "data": "a"
            }
        ],
        "d": [
            {
                "data": "a"
            }
        ],
        "a": [
            {
                "data": "a"
            }
        ]
    }
}

looks like property ordered=True on ChildSchema class is not working I have been looking for that in some posts and looks like the issue happens when you mix Nested fields and the ordered property.

This is my stack

flask-marshmallow==0.14.0
marshmallow==2.21.0
marshmallow-sqlalchemy==0.23.1

Solution

  • I see that you can try two different strategies:

    Add this config line to your code after the app definition:

    app = Flask (__ name__)
    app.config ['JSON_SORT_KEYS'] = False
    

    that suppress the flask dictionary keys sorting and forces to respect the defined order.

    Also you can try adding at ParentSchema class the same meta for sorting keys, since ChildSchema is contained on ParentSchema; we need to specify to ParentSchema to respect keys order too.

    something like

    class ParentSchema(Schema):
        class Meta:
            ordered = True
    
        response = fields.Nested(ChildSchema)
    

    I hope you find this useful, regards