Marshmallow: ordered = True not respected

Created on 7 Aug 2015  Â·  10Comments  Â·  Source: marshmallow-code/marshmallow

class BaseSchema(Schema):
     id = fields.Int(dump_only=True)

class LineItemSchema(BaseSchema):
    name = fields.Str(attribute='label')

class CampaignSchema(BaseSchema):
    name = fields.Str(attribute='campaign_name')
    line_items = fields.Nested(LineItemSchema, many=True)

    class Meta:
        fields = ("id", "name", "line_items")
        ordered = True

When I run:
result = campaign_schema.dump(campaign)
json.dumps(result.data)

I get this output:

{
    "id": 1, 
    "line_items": [
        {
            "id": 1, 
            "name": "mpu"
        }, 
        {
            "id": 3, 
            "name": "banner"
        }
    ], 
    "name": "test"
}

I had a look in my debugger - think it's something to do with that some of the field names are the same? Perhaps something to do with how ret is constructed here: https://github.com/marshmallow-code/marshmallow/blob/dev/marshmallow/schema.py#L729

Let me know if I'm missing something in my config somewhere!

bug

Most helpful comment

This also happens in flask-smorest 0.22.0. All you need to do is disable JSON_SORT_KEYS in your config, as @halfar-aspire mentioned.

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

All 10 comments

Thanks for reporting. What version of marshmallow are you using?

I've tried in both 1.2.6 and 2.0.0b4 :)

On Saturday, 8 August 2015, Steven Loria [email protected] wrote:

Thanks for reporting. What version of marshmallow are you using?

—
Reply to this email directly or view it on GitHub
https://github.com/marshmallow-code/marshmallow/issues/257#issuecomment-128989481
.

Hm, I have not been able to reproduce this on either version. Do you have any other code that will produce the bug?

Interesting! I wonder if it's something to do with SQLAlchemy or the attribute name stuff? Here are my models, and my code for the route... Thanks for looking by the way!

class Campaign(Base):
    __tablename__ = 'campaign'

    id = Column(BigInteger, primary_key=True)
    campaign_name = Column(String(45))
    line_items = relationship("LineItem")

class LineItem(Base):
    __tablename__ = 'line_item'

    id = Column(BigInteger, primary_key=True)
    width = Column(Integer)
    height = Column(Integer)
    tag = Column(Text)
    label = Column(String(45))
    campaign_id = Column(BigInteger, ForeignKey('campaign.id'), nullable=False,
                     index=True)
    ext_tag = Column(Text)
    client_account_id = Column(BigInteger)

And my query:

campaigns = session.query(Campaign).all()
result = campaign_schema.dump(campaigns, many=True)
resp.body = json.dumps(result.data)

Sorry, but I haven't been able to reproduce this. Closing this for now. Best of luck! Feel free to re-open if you discover more about the problem.

This has something to do with json.dumps. I traced it into that method and it is not respecting the OrderedDict at least in Python 3.5.1. If you are using Flask-Restful, this could be why:
http://flask-restful-cn.readthedocs.org/en/latest/extending.html
"Note
If the application is running in debug mode (app.debug = True) and either sort_keys or indent are not declared in the RESTFUL_JSON configuration setting, Flask-RESTful will provide defaults of True and 4 respectively."

By default Flask will serialize JSON objects in a way that the keys are ordered. You can override the default behavior by changing the variable JSON_SORT_KEYS = False in your project config file, This is not recommended but might give you a performance improvement on the cost of cacheability.

This also happens in flask-smorest 0.22.0. All you need to do is disable JSON_SORT_KEYS in your config, as @halfar-aspire mentioned.

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

It should not happen in flask-smorest because we don't use Flask dump but json dump.

https://github.com/marshmallow-code/flask-smorest/blob/4b27aecf52b105657b0c8d4632712c642ec9ce7e/flask_smorest/spec/__init__.py#L95-L101

py def _openapi_json(self): """Serve JSON spec file""" # We don't use Flask.jsonify here as it would sort the keys # alphabetically while we want to preserve the order. return current_app.response_class( json.dumps(self.spec.to_dict(), indent=2), mimetype='application/json')

@lafrech It does not happen for the schema / spec, but JSON_SORT_KEYS does have a influence on the order of the keys in the data.

I think this is the relevant part: https://github.com/marshmallow-code/flask-smorest/blob/4b27aecf52b105657b0c8d4632712c642ec9ce7e/flask_smorest/response.py#L101

Was this page helpful?
0 / 5 - 0 ratings

Related issues

agatheblues picture agatheblues  Â·  3Comments

rastikerdar picture rastikerdar  Â·  3Comments

ambye85 picture ambye85  Â·  4Comments

Ovyerus picture Ovyerus  Â·  3Comments

jayennis22 picture jayennis22  Â·  4Comments