fix(config): preserve explicit null when merging objects
This commit is contained in:
parent
ccc60b4245
commit
0c1d3e30b6
|
@ -1,5 +1,6 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
|
#include <fmt/ostream.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
|
@ -86,11 +87,15 @@ void Config::mergeConfig(Json::Value &a_config_, Json::Value &b_config_) {
|
||||||
a_config_ = b_config_;
|
a_config_ = b_config_;
|
||||||
} else if (a_config_.isObject() && b_config_.isObject()) {
|
} else if (a_config_.isObject() && b_config_.isObject()) {
|
||||||
for (const auto &key : b_config_.getMemberNames()) {
|
for (const auto &key : b_config_.getMemberNames()) {
|
||||||
if (a_config_[key].isObject() && b_config_[key].isObject()) {
|
// [] creates key with default value. Use `get` to avoid that.
|
||||||
|
if (a_config_.get(key, Json::Value::nullSingleton()).isObject() &&
|
||||||
|
b_config_[key].isObject()) {
|
||||||
mergeConfig(a_config_[key], b_config_[key]);
|
mergeConfig(a_config_[key], b_config_[key]);
|
||||||
} else if (a_config_[key].isNull()) {
|
} else if (!a_config_.isMember(key)) {
|
||||||
// do not allow overriding value set by top or previously included config
|
// do not allow overriding value set by top or previously included config
|
||||||
a_config_[key] = b_config_[key];
|
a_config_[key] = b_config_[key];
|
||||||
|
} else {
|
||||||
|
spdlog::trace("Option {} is already set; ignoring value {}", key, b_config_[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -67,6 +67,8 @@ TEST_CASE("Load simple config with include", "[config]") {
|
||||||
REQUIRE(data["height"].asInt() == 30);
|
REQUIRE(data["height"].asInt() == 30);
|
||||||
// config override behavior: preserve value from the top config
|
// config override behavior: preserve value from the top config
|
||||||
REQUIRE(data["position"].asString() == "top");
|
REQUIRE(data["position"].asString() == "top");
|
||||||
|
// config override behavior: explicit null is still a value and should be preserved
|
||||||
|
REQUIRE((data.isMember("nullOption") && data["nullOption"].isNull()));
|
||||||
}
|
}
|
||||||
SECTION("select configs for configured output") {
|
SECTION("select configs for configured output") {
|
||||||
auto configs = conf.getOutputConfigs("HDMI-0", "Fake HDMI output #0");
|
auto configs = conf.getOutputConfigs("HDMI-0", "Fake HDMI output #0");
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
"layer": "top",
|
"layer": "top",
|
||||||
"position": "bottom",
|
"position": "bottom",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"output": ["HDMI-0", "DP-0"]
|
"output": ["HDMI-0", "DP-0"],
|
||||||
|
"nullOption": "not null"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"include": ["test/config/include-1.json", "test/config/include-2.json"],
|
"include": ["test/config/include-1.json", "test/config/include-2.json"],
|
||||||
"position": "top"
|
"position": "top",
|
||||||
|
"nullOption": null
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue