0

I need to create a data payload for a restful web api. The template for the dict contains some optional keys. The usual way is to create a dict with all the required keys and then check and add optional keys one by one:

def create_payload(key1, key2, ..., key10=None,key11=None):

    data = {
        'key1' : key1,
        'key2' : key2,
        ...
        'nested' : {}
    }
    if key10:
        data[ 'nested' ][ 'key10' ] = key10
    if key11:
        data[ 'key11' ] = key11

    return data

Is there an alternative way to start with the data template and then automatically delete optional keys that are None?

def create_payload(key1, key2, ..., key10=None,key11=None):

    data = {
        'key1' : key1,
        'key2' : key2,
        ...
        'nested' : {
            'key10' : key10
        },
        'key11' : key11 
    }
    # delete keys that are None

    return data

UPDATE Some of you suggested doing dictionary comprehension to remove None keys:

{k: v for k, v in metadata.items() if v is not None}

In my attempt to create a simple example, I didn't account for the possibility that some of the keys may be nested. (I am updating the example above.) Is there a dictionary comprehension that can exclude None values inside nested keys?

user3628119
  • 355
  • 5
  • 15
  • Please check *args and **kwargs https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3 – Krystian Kazimierczak Aug 06 '18 at 08:38
  • Possible duplicate of [Efficient way to remove keys with empty strings from a dict](https://stackoverflow.com/questions/12118695/efficient-way-to-remove-keys-with-empty-strings-from-a-dict) – Brown Bear Aug 06 '18 at 08:44
  • Structure of *data* looks strange, maybe you should show how does it used. – Waket Zheng Aug 06 '18 at 09:58

1 Answers1

1

Yes, you can use for example dictionary comprehension:

return {k: v for k, v in data.items() if v is not None}

or for a nested structure:

def create_payload(key1, key2, key10=None,key11=None):
    data = {
        # ...
    }
    def strip_nones(dc):
        return {
            k: strip_nones(v) if isinstance(v, dict) else v
            for k, v in dc.items() if v is not None
        }
    return strip_nones(data)

We create thus a new dictionary that only retains the non-None values.

But you can probably reduce the amount of logic to:

def create_payload(**kwargs):
    return {k: v for k, v in kwargs.items() if v is not None}

Here you can call the create_payload function will all kinds of parameters, and it will return a dictionary with all non-None values. If you want to include those as well, it is even simply:

def create_payload(**kwargs):
    return kwargs
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555