0

I am new to Python and working on revising some existing code.

There is a JSON string coming into a Python function that looks like this:

{"criteria": {"modelName":"='ALL'", "modelName": "='NEW'","fields":"*"}}

Right now it appears a dictionary is being used to create a string:

crit=data['criteria']
for crit_key in crit 
   crit_val = crit[crit_key]
   sql+ = sql+= ' and ' + crit_key + crit_val 

When the sql string is printed, only the last 'modelName' appears. It seems like a dictionary is being used as modelName is a key so the second modelName overwrites the first? I want the "sql" string in the end to contain both modelNames.

martineau
  • 119,623
  • 25
  • 170
  • 301
Dan
  • 57
  • 3
  • 11
  • you'll have to edit the string before parsing it into a dictionary – Jean-François Fabre Nov 30 '16 at 16:36
  • Apart from the bug -- is that JSON coming from the outside world? This looks like a huge SQL injection problem. – RemcoGerlich Nov 30 '16 at 16:36
  • excluding the SQL injection issue, really what I think I need to do is have a list. Am I correct that the existing code is a dictionary? – Dan Nov 30 '16 at 16:37
  • If you parse it with `json.loads` or similar, then yes it produces a dictionary and will only include one copy of each key. Whether your JSON is valid is controversial. – RemcoGerlich Nov 30 '16 at 16:42
  • Python dictionaries must have unique key values, but the JSON string coming in is trying to associate two different value with the key `"modelName"`. Last one put into the dictionary will be the only one preserved. – martineau Nov 30 '16 at 16:42
  • OK. So assuming I have to work with the JSON string as it comes in , what would be best to create the output string to have both modelName values? – Dan Nov 30 '16 at 16:45
  • Try to find a parsing library that parses such JSON to a multidict, or write your own. – RemcoGerlich Nov 30 '16 at 16:48

1 Answers1

0

edited because of OP comments

Well, if you can't update your JSON and have to deal with.

You can make something like:

data = '{"criteria": {"modelName":"=\'ALL\'", "modelName": "=\'NEW\'","fields":"*"}}'

import json

def dict_raise_on_duplicates(ordered_pairs):
    d = {}
    duplicated = []
    for k, v in ordered_pairs:
        if k in d:
            if k not in duplicated:
                duplicated.append(k)
                d[k] = [d[k]] + [v]
            else:
                d[k].append(v)
        else:
            d[k] = v
    return d

print json.loads(data, object_pairs_hook=dict_raise_on_duplicates)

In this example, data is the JSON string with duplicated keys. According to json.loads allows duplicate keys in a dictionary, overwriting the first value I just force json.load to handle duplicate keys.

If a duplicated key is spotted, it will create a new list containing current key data and add new value. After, it will only append news values in created list.

Output:

{u'criteria': {u'fields': u'*', u'modelName': [u"='ALL'", u"='NEW'"]}}

You will have to update your code anyway, but you now can handle it.

Community
  • 1
  • 1
Arount
  • 9,853
  • 1
  • 30
  • 43