1

I'm trying to compare two complex json strings using python but I'm having some issues. The two strings I have are the same, but some fields of child elements appear in different orders.

EG:

a = """
{
   "sgroupname":"windows_securezone",
   "ipperms":[
      {
         "IpProtocol":"-1",
         "IpRanges":[
            {
               "CidrIp":"194.66.78.xx/32"
            },
            {
               "CidrIp":"86.17.73.xx/32"
            }
         ],
         "UserIdGroupPairs":[

         ],
         "PrefixListIds":[

         ]
      }
   ]
}
"""
b = """
{
   "sgroupname":"windows_securezone",
   "ipperms":[
      {
         "IpProtocol":"-1",
         "IpRanges":[
            {
               "CidrIp":"86.17.73.xx/32"
            },
            {
               "CidrIp":"194.66.78.xx/32"
            }
         ],
         "UserIdGroupPairs":[

         ],
         "PrefixListIds":[

         ]
      }
   ]
}
"""

The fact that the IpRanges list under the ipperms element returns in a different order seems to break the comparison; if I switch them to the same order the comparison works correctly.

I've tried using OrderedDict, the json.dumps 'sort_keys=True' parameter, and using the sorted() function, but I can't get the strings to compare. Any ideas?

Any help would be greatly appreciated!

5
  • 1
    sort_keys isn't going to help you because IpRanges is a list. It already has an ordering. If you wanted to compare these, you would need to sort any lists contained in your objects first...which is going to be tricky, since the members of those lists are dicts, which are not inherently sortable. Commented Apr 7, 2016 at 16:29
  • Is there some reason you can't parse them both back to Python native types with json.loads and just do plain equality tests? Also, what larsks said. :-) Commented Apr 7, 2016 at 16:34
  • @ShadowRanger The issue is the data will not necessarily always be in this format; sometimes there will be lists present, other times not, so I'm unsure how I could implement that solution... Commented Apr 7, 2016 at 16:38
  • You can't without first writing some code to normalize the data present in your two dictionaries. Commented Apr 7, 2016 at 16:42
  • Bugger. I guess in that case I'll have to sort the data before it is stored and hopefully then the comparison should be better. Thanks! Commented Apr 7, 2016 at 17:02

1 Answer 1

1

try this approach:

In [200]: a
Out[200]:
{'ipperms': [{'IpProtocol': '-1',
   'IpRanges': [{'CidrIp': '194.66.78.xx/32'}, {'CidrIp': '86.17.73.xx/32'}],
   'PrefixListIds': [],
   'UserIdGroupPairs': []}],
 'sgroupname': 'windows_securezone'}

In [201]: b
Out[201]:
{'ipperms': [{'IpProtocol': '-1',
   'IpRanges': [{'CidrIp': '86.17.73.xx/32'}, {'CidrIp': '194.66.78.xx/32'}],
   'PrefixListIds': [],
   'UserIdGroupPairs': []}],
 'sgroupname': 'windows_securezone'}

In [202]: def ordered(obj):
   .....:         if isinstance(obj, dict):
   .....:                 return sorted((k, ordered(v)) for k, v in obj.items())
   .....:         if isinstance(obj, list):
   .....:                 return sorted(ordered(x) for x in obj)
   .....:         else:
   .....:                 return obj
   .....:

In [203]: ordered(a) == ordered(b)
Out[203]: True

In [204]: a == b
Out[204]: False
Sign up to request clarification or add additional context in comments.

3 Comments

If you try that with the original data, you'll see that frozenset is actually discarding information. All that tells you is whether a and b have the same keys (i.e., you are essentially compareing a.keys() to b.keys()).
@larsks, tried it with the original data - it's still working. what am i doing wrong?
Look at the return value of, e.g., frozenset(a). That only considers the top-level key names from the original dictionary, and does not thing to compare the values.

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.