How to serialize a Marshmallow field under a different name

给你一囗甜甜゛ 提交于 2021-01-17 07:21:36

问题


I want a Marshmallow Schema with the following output json -

{
  "_id": "aae216334c3611e78a3e06148752fd79",
  "_time": 20.79606056213379,
  "more_data" : {...}
}

Marshmallow doesn't serialize private members so this is as close as I can get -

class ApiSchema(Schema):
    class Meta:
        strict = True

    time = fields.Number()
    id = fields.String()

But I do need the underscores in the output json.

Is there a way to tell Marshmallow to serialize the fields using different names?


回答1:


https://marshmallow.readthedocs.io/en/2.x-line/quickstart.html#specifying-attribute-names

Even though the docs are for version 2, this seems to still work as of 3.5.1. The stable version 3 docs will not have this example.

class ApiSchema(Schema):
  class Meta:
      strict = True

  _time = fields.Number(attribute="time")
  _id = fields.String(attribute="id")



回答2:


The accepted answer (using attribute) didn't work for me, possibly because:

Note: This should only be used for very specific use cases such as outputting multiple fields for a single attribute. In most cases, you should use data_key instead.

However data_key worked nicely:

class ApiSchema(Schema):
    class Meta:
        strict = True

    _time = fields.Number(data_key="time")
    _id = fields.String(data_key="id")



回答3:


The answer's well documented in Marshmallows api reference.

I need to use dump_to :

class ApiSchema(Schema):
    class Meta:
        strict = True

    time = fields.Number(dump_to='_time')
    id = fields.String(dump_to='_id')



回答4:


You can override the dump method to prepend underscores to selected fields before returning the serialised object:

class ApiSchema(Schema):
    class Meta:
        strict = True

    time = fields.Number()
    id = fields.String()

    def dump(self, *args, **kwargs):
        special = kwargs.pop('special', None)
        _partial = super(ApiSchema, self).dump(*args, **kwargs)
        if special is not None and all(f in _partial for f in special):
            for field in special:
                _partial['_{}'.format(field)] = _partial.pop(field)
        return _partial

api_schema = ApiSchema(...)
result = api_schema.dump(obj, special=('id', 'time'))

You can also use the post_dump decorator on a separate custom method without having to override dump, but then, you may have to hardcode the fields to-be-modified as part of the class, which may be inflexible depending on your use case.



来源:https://stackoverflow.com/questions/44434180/how-to-serialize-a-marshmallow-field-under-a-different-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!