7

I am building an API using flask-restful. I am also using flask-resfulplus for generating swagger documentation. I want to return a dictionary of items where the key is going to vary depending on the item. My model looks like this:

item = api.model('Item',{
            'item':fields.Integer()}) <- This is wrong


ItemModel = api.model('ItemsList', {
        '_header': fields.Nested(_header),
        'items':fields.Nested(item)
})

Note that I tried a few variations of this, but nothing seems to work; this is just the latest interation.

And the response I am looking for is something like this.

{
        '_header':{} <-This works fine
        'items': {
         'item1':5,
         'item2':2
         }
    }

Item in the items dictionary will have a different key for the item and the count as the value.

I've tried setting the item field to field.Raw() and it works fine, but then it doesn't get displayed in the swagger documentation.

Note that I do not want to return a list of dictionaries, which I have working.

Thanks

nick_v1
  • 1,554
  • 15
  • 27
  • Can you provide a fuller example? You have an integer DB field, but you want that field to generate a nested dictionary when serialized? Why? – jumbopap Jan 15 '16 at 03:22
  • Thanks for the comment. Check out the desired output. item1: 5, item2 : 2, etc.... how do I get the key to be different for each item? – nick_v1 Jan 16 '16 at 12:31
  • You're going to have to write a custom serializer. Flask-Restful has no knowledge of the database outside of the object it is marshalling. – jumbopap Jan 17 '16 at 06:28
  • Is there a way for me to somehow manually overwrite what it generates in the documentation and marshal the output myself? – nick_v1 Jan 19 '16 at 19:10
  • Hello! Did you manage to find a solution? – brezniczky May 05 '18 at 01:25

1 Answers1

0

Sometimes you have your own custom formatting needs. You can subclass the fields.Raw class and implement the format function. This is especially useful when an attribute stores multiple pieces of information. e.g. a bit-field whose individual bits represent distinct values. You can use fields to multiplex a single attribute to multiple output values.

If you don’t know the name(s) of the field(s) you want to unmarshall, you can use Wildcard.

>>> from flask_restplus import fields, marshal
>>> import json
>>>
>>> wild = fields.Wildcard(fields.String)
>>> wildcard_fields = {'*': wild}
>>> data = {'John': 12, 'bob': 42, 'Jane': '68'}
>>> json.dumps(marshal(data, wildcard_fields))
>>> '{"Jane": "68", "bob": "42", "John": "12"}'

The name you give to your Wildcard acts as a real glob as shown below.

>>> from flask_restplus import fields, marshal
>>> import json
>>>
>>> wild = fields.Wildcard(fields.String)
>>> wildcard_fields = {'j*': wild}
>>> data = {'John': 12, 'bob': 42, 'Jane': '68'}
>>> json.dumps(marshal(data, wildcard_fields))
>>> '{"Jane": "68", "John": "12"}'

Note It is important you define your Wildcard outside your model (ie. you cannot use it like this: res_fields = {'': fields.Wildcard(fields.String)})* because it has to be stateful to keep a track of what fields it has already treated.

Subir Verma
  • 306
  • 2
  • 8