2016-04-07 18 views
1

私はPythonを使用して2つの複雑なjson文字列を比較しようとしていますが、いくつか問題があります。私が持っている2つの文字列は同じですが、子要素のいくつかのフィールドは異なる順序で表示されます。Pythonでの複雑なjson文字列の比較

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":[ 

     ] 
     } 
    ] 
} 
""" 

異なる順序でipperms要素戻っ下IpRangesリストは、比較を破るように見えるという事実。私はそれらを同じ順序に切り替えると、比較が正しく機能します。

私はOrderedDict、json.dumps 'sort_keys = True'パラメータ、sorted()関数を使用してみましたが、比較する文字列を取得できません。何か案は?

ご協力いただければ幸いです!

+1

'sort_keys'は*' IpRanges'は*リストであるので、お手伝いをするつもりはありません。すでに注文しています。これらを比較したい場合は、最初にオブジェクトに含まれるリストをソートする必要があります。これらのリストのメンバーは本質的にソート可能ではないディクテーションであるため、扱いにくくなります。 – larsks

+0

'json.loads'を使ってPythonのネイティブ型に戻って解析することができない何らかの理由がありますか?また、ラークスは言った。 :-) – ShadowRanger

+0

@ShadowRanger問題はデータが必ずしもこの形式であるとは限りません。時々そこにリストが存在する、他の時ではないので、私はその解決法をどのように実装できるか確信しています... – Ben

答えて

1

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 
+0

元のデータでそれを試してみると、frozensetが実際に情報を破棄していることがわかります。 aとbが同じキーを持っているかどうかを示すだけです(つまり、a.keys()とb.keys()を本質的に比較しています)。 – larsks

+0

@larsksさん、元のデータで試してみました。まだ動作しています。私は間違って何をしていますか? – MaxU

+0

たとえば、 'frozenset(a)'の戻り値を見てください。これは、元の辞書のトップレベルのキー名のみを考慮し、値を比較することはありません。 – larsks