Python / JSON:合并默认和用户配置

时间:2015-03-18 14:19:53

标签: python json configuration

我在python应用程序中使用JSON配置文件。我想要一个带有分层图层的默认配置 用户配置应仅包含与默认值不同的参数。 我目前的解决方案是:

# default.json
{
    "parA" : 1,
    "parB" : {
       "sparA" : 0,
       "sparB" : 1
    }
}`

# user.json
{
    "parB" : {
       "sparB" : 9
    }
}

配置由

加载
default_json = open("default.json")
default_config = json.load(default_json)
default_json.close()


user_json = open("user.json")
user_config = json.load(user_json)
user_json.close()  

config = default_config.copy()
config.update(user_config)

问题在于,整个密钥" parA"被覆盖,以便" sparA"被删除。 是否有一种简单的方法可以仅覆盖子键但从不覆盖整个父键?

1 个答案:

答案 0 :(得分:3)

可以做到,虽然它有点微妙。下面假设结构兼容性(例如,你不是试图将非dict合并到dict等),而在非dicts的情况下,“merge”是一个简单的替代。

它还假设可以就地修改基础对象(看起来是这样的,因为你无论如何要更新副本;如果后者不是这样的话,那就没什么大不了的,只需添加一个复制语句,如在base_obj = dict(base_obj)循环之前的for ...:

def selective_merge(base_obj, delta_obj):
    if not isinstance(base_obj, dict):
        return delta_obj
    common_keys = set(base_obj).intersection(delta_obj)
    new_keys = set(delta_obj).difference(common_keys)
    for k in common_keys:
        base_obj[k] = selective_merge(base_obj[k], delta_obj[k])
    for k in new_keys:
        base_obj[k] = delta_obj[k]
    return base_obj

这适用于您的示例,但是如果例如使用您的default.jsonuser.json就是'{"parB": 23}'(将非字典合并为dict违反了结构兼容性约束;我不确定在这种情况下你想要会发生什么。)

因此,一旦您将该功能调整为您的确切规格,您只需要在给定的代码中替换

config.update(user_config)

config = selective_merge(config, user_config)