2

I am comparing if all elements of a json object are inside another json. for that i grab all keys in one layer of the small one and check if they are in the big one and if they are the same. to go into a deeper layer i call the function giving it the element that contains the deeper layer. (in this funtion now i detect the deeper layer with the key "results" but i futur it will be changed to a variable key. my Problem is that i can't call the recursive function. it sais "string indices must be integers, not unicode" in the script when trying to call the function in the function.

def compareJson(example_json_s, target_json_s): 
    #parsed_json
    example_json = example_json_s
    target_json = target_json_s
    p = 0
    keys = []
    for key in example_json.keys(): 
        keys.insert(p, key)
        p = p + 1

    passed = 0;
    for x in keys: 
        print "Keys"
        if x != "results": 
            if not x in target_json or x not in example_json.keys() and not example_json[x] == target_json[x]: 
                passed = 1
        else:
            print """###inhabits "results " going one layer deeper"""
        compareJson(example_json[key], target_json[key])
    return passed

and some example json objects:

{
    "results": {
        "clock": true,
        "update": false,
        "autoreg": false
    }
} 

{
    "id": "1523",
    "dlid": "009029",
    "serial": "1017030022",
    "statuscode": 128,
    "results": {
        "event": true,
        "counter": true,
        "clock": true,
        "eqep": true,
        "usb": false,
        "modem": true,
        "sim": true,
        "pin": true,
        "encrypt": false,
        "upload": true,
        "update": true,
        "autoreg": true
    },
    "ok": false,
    "confirmed": false
}

And the Error code here:

Traceback (most recent call last):
  File "/home/philip/Desktop/empfang_test.py", line 199, in <module>
    empfange() #Programm wartet in einer Endlosschleife auf eingehende Nachrichten.
  File "/home/philip/Desktop/empfang_test.py", line 193, in empfange
    checkvalue=compareJson(json.loads(config[1][1]),parsed_json_dummy)
  File "/home/philip/Desktop/empfang_test.py", line 183, in compareJson
    compareJson(example_json[key],target_json[key])   
TypeError: string indices must be integers, not str
3
  • Can you fix indentation and add the complete error message? Commented Jan 13, 2016 at 9:21
  • what is the desired output? True/False or a list (or dict) of which fields are present? Commented Jan 13, 2016 at 9:41
  • What about fixture pythonhosted.org/testfixtures/comparing.html that provide dict comparison. Commented Jan 13, 2016 at 10:09

2 Answers 2

2

Here is my solution

def contained(a, b):
    """ checks if dictionary a is fully contained in b """
    if not isinstance(a, dict):
        return a == b
    else:
        return all(contained(v, b.get(k)) for k, v in a.items())

print(contained(d1, d2))

which, for your input gives False and for

d1 = {
      "results": {
                  "clock": True,
                  "update": True,
                  "autoreg": True
                 }
     }

gives True

and for

d1 = {
    "results": {
        "clock": True,
        "update": True,
        "autoreg": True,
        "qqq": True
    }
}

i.e. a key is missing from the target (e.g. qqq), it gives False

Of course you can call it with

contained(json.loads(example_json_s), json.loads(target_json_s))

when starting from a JSON string

Sign up to request clarification or add additional context in comments.

2 Comments

I think that if there is a k such that k not in b it should return False?
@MrHug yes, fixed. Thank you
0

I think the following code should do the trick:

def compareJson(example_json_s, target_json_s):
 example_json = json.loads(example_json_s)
 target_json = json.loads(target_json_s)
 return compareParsedJson(example_json, target_json)

def compareParsedJson(example_json, target_json):   
 for x in example_json:
   if type(example_json[x]) is not dict:
     if not x in target_json or not example_json[x] == target_json[x]:
       return False
   else:
     if x not in target_json or not compareParsedJson(example_json[x], target_json[x]):
      return False

 return True

In the first function we parse the full JSON object (including the recursive parts). The second analyses them.

I have made several changes to your code.

  • There is no need to get a list of the keys first, you can just iterate over example_json.keys(). Additionally I would have replaced it with keys.append(key) in your example.
  • The function checks if the type of the nested json object is now a dict (it has already been parsed). If not, then it compares them, if so, then it goed into the next one. You might want to add a similar clause for lists.
  • The function returns False as soon as a part of the JSON is not the same.

EDIT: In response to your posted error code, I think you might not have parsed the json correctly. I took your comment #parsed_json to mean that you had, but I think you were missing the json.loads method calls I included in my code example above..?

2 Comments

You are most welcome. Thank you for the acceptance of the answer.
On a side note, avoid using dict.keys() when all you want is to iterate over a dictionary. Simply remove the .keys() to get for k in dict:. Ref: stackoverflow.com/questions/4730993/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.