Convert QueryDict into list of arguments
Question: I'm receiving via POST request the next payload through the view below:

    
    
    class CustomView(APIView):
    
    """
    POST data
    """
    def post(self, request):                
        extr= externalAPI()
        return Response(extr.addData(request.data))
    

And in the `externalAPI` class I have the `addData()` function where I want to
convert _QueryDict_ to a simple list of arguments:

    
    
    def addData(self, params):        
        return self.addToOtherPlace(**params)   
    

In other words, what I get in params is somethin like:

    
    
    <QueryDict: {u'data': [u'{"object":"a","reg":"1"}'], u'record': [u'DAFASDH']}>
    

And I need to pass it to the addToOtherPlace() function like:

    
    
    addToOtherPlace(data={'object':'a', 'reg': 1}, record='DAFASDH')
    

I have tried with different approaches but I have to say I'm not very familiar
with dictionaries in python.

Any help would be really appreciated.

Thanks!


Answer: You can write a helper function that walks through the _QueryDict_ object and
converts valid _JSON_ objects to Python objects, string objects that are
digits to integers and returns the first item of lists from lists:

    
    
    import json
    
    def restruct(d):
        for k in d:
            # convert value if it's valid json
            if isinstance(d[k], list):
                v = d[k]
                try:
                    d[k] = json.loads(v[0])
                except ValueError:
                    d[k] = v[0]
    
            # step into dictionary objects to convert string digits to integer
            if isinstance(d[k], dict):
                restruct(d[k])
            elif d[k].isdigit():
                d[k] = int(d[k])
    
    
    params = {u'data': [u'{"object":"a","reg":"1"}'], u'record': [u'DAFASDH']}
    restruct(params)
    print(params)
    # {'record': 'DAFASDH', 'data': {'object': 'a', 'reg': 1}}
    

Note that this approach modifies the initial object _in-place_. You can make a
`deepcopy`, and modify the copy instead if you're going to keep the original
object intact:

    
    
    import copy
    
    def addData(self, params):
        params_copy =  copy.deepcopy(params)  
        restruct(params_copy)   
        return self.addToOtherPlace(**params_copy) 
    

