Python/JSON:合并默认和用户配置
Python/JSON: Merge default and user 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" 被删除。
有没有一种简单的方法可以只覆盖子密钥而不覆盖整个父密钥?
可以做到,虽然有点微妙。以下假定结构兼容性(例如,您不试图将非字典合并到字典等)并且在非字典的情况下 "merge" 是一个简单的替换。
它还假设就地修改基础对象是可以的(看起来是这样,因为你无论如何都要更新一个副本;如果后者不是这种情况,那没什么大不了的,只需添加一个复制语句例如 base_obj = dict(base_obj)
就在 for
循环之前)...:[=18=]
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.json
,则 user.json
是 '{"parB": 23}'
(将非字典合并为字典)违反了结构兼容性约束;我不确定在这种情况下您希望发生什么。
因此,根据您的确切规格调整函数后,您只需在给定的代码中替换,
config.update(user_config)
和
config = selective_merge(config, user_config)
我在 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" 被删除。 有没有一种简单的方法可以只覆盖子密钥而不覆盖整个父密钥?
可以做到,虽然有点微妙。以下假定结构兼容性(例如,您不试图将非字典合并到字典等)并且在非字典的情况下 "merge" 是一个简单的替换。
它还假设就地修改基础对象是可以的(看起来是这样,因为你无论如何都要更新一个副本;如果后者不是这种情况,那没什么大不了的,只需添加一个复制语句例如 base_obj = dict(base_obj)
就在 for
循环之前)...:[=18=]
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.json
,则 user.json
是 '{"parB": 23}'
(将非字典合并为字典)违反了结构兼容性约束;我不确定在这种情况下您希望发生什么。
因此,根据您的确切规格调整函数后,您只需在给定的代码中替换,
config.update(user_config)
和
config = selective_merge(config, user_config)