-
json里面的key默认是唯一,但是有些情况下json里面的key值并不唯一。比如我在分析WIFI协议的时候
-
这时候就需要解决key重复的问题。那么如何解决呢?
-
不处理的情况
例如:{"key":"1", "key":"2", "key":"3", "key2":"4"}
把上面的值写入到json文件中。
-
如果不处理重复key的问题,输出结果会怎么样? 代码如下:
import json json_list={"key": "1", "key": "2", "key": "3", "key2": "4"} with open("4.json",'r',encoding='utf8') as fp: json_data = json.load(fp) print(json_data)
-
重复的key,程序默认只保留了最后一个值,这样显然不符合我们的需求。我们希望的结果是:
{ "key":["1","2","3"], "key2":"4" }
解决方案
-
首先来看一下解析函数load函数,如下:
def load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing a JSON document) to a Python object. ``object_hook`` is an optional function that will be called with the result of any object literal decode (a ``dict``). The return value of ``object_hook`` will be used instead of the ``dict``. This feature can be used to implement custom decoders (e.g. JSON-RPC class hinting). ``object_pairs_hook`` is an optional function that will be called with the result of any object literal decoded with an ordered list of pairs. The return value of ``object_pairs_hook`` will be used instead of the ``dict``. This feature can be used to implement custom decoders. If ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority.
-
object_hook 是一个可选函数,将使用任何对象文字解码(dict)的结果调用。 object_hook 的返回值将被用来代替dict。 此功能可用于实现自定义解码器(例如 JSON-RPC 类提示)。 object_pairs_hook 是一个可选函数,将使用任何对象字面量的结果以有序的对列表解码的结果调用。 object_pairs_hook 的返回值将被用来代替dict。 此功能可用于实现自定义解码器。 如果还定义了“object_hook”,则“object_pairs_hook”优先。 object_pairs_hook是个回调函数,在解析json文本的时候会调用它并更改返回的结果。
-
为了得到前述的结果,我们定义如下的hook函数:
def obj_pairs_hook(lst): result={} count={} for key,val in lst: if key in count:count[key]=1+count[key] else:count[key]=1 if key in result: if count[key] > 2: result[key].append(val) else: result[key]=[result[key], val] else: result[key]=val return result
-
然后在执行load的时候加上这个函数。代码如下:
import json def obj_pairs_hook(lst): result = {} count = {} for key, val in lst: if key in count: count[key] = 1 + count[key] else: count[key] = 1 if key in result: if count[key] > 2: result[key].append(val) else: result[key] = [result[key], val] else: result[key] = val return result def init(): load_data = {} with open("world-history.json", 'r') as f: content = f.read() load_data = json.loads(content, object_pairs_hook=obj_pairs_hook) with open("world-history-new.json", 'w') as f2: b = json.dumps(load_data["result"]["event"]) f2.write(b) pass if __name__ == '__main__': init()
文章评论