Address the review of json_view element access
From gregmarr's review of #5622: - count() counts every member with the key, so count(key) > 1 detects duplicate keys; it was contains() as 0/1 before. - get_to() passes types that get<T>() does not convert directly to from_json with the existing value, as basic_json::get_to() does, so that a from_json which sets only the fields present keeps the others. - array_index() checks the empty token and "-" first; the results are unchanged. - Docs: no "if an exception is thrown" where a view never changes anything; the borrowed source must also stay unmodified; items() on a temporary view is safe; back()/front() notes shortened; the basic_json see-also entries say how the view's results can differ. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
27 files changed
+239
-114
No files matched your search
@@ -731,7 +731,12 @@ void check_access(const ordered_json_view& v, const ordered_json& j)
|
||||
++members;
|
||||
const std::string key(it.key().data(), it.key().size());
|
||||
CHECK(v.contains(key));
|
||||
CHECK(v.count(key) == 1);
|
||||
std::size_t occurrences = 0;
|
||||
for (auto other = v.begin(); other != v.end(); ++other)
|
||||
{
|
||||
occurrences += other.key() == it.key() ? 1 : 0;
|
||||
}
|
||||
CHECK(v.count(key) == occurrences);
|
||||
// lookups find the first member with the key, which is this one if
|
||||
// there is no earlier one
|
||||
if (std::find(keys.begin(), keys.end(), key) != keys.end())
|
||||
@@ -839,7 +844,8 @@ TEST_CASE("json_view element access and iteration")
|
||||
CHECK(v.find("a") == v.begin());
|
||||
CHECK(v.find("a").value().materialize() == 1);
|
||||
CHECK(v.find("b") == std::next(v.begin()));
|
||||
CHECK(v.count("a") == 1);
|
||||
CHECK(v.count("a") == 2); // every member, unlike materialize()
|
||||
CHECK(v.count("b") == 1);
|
||||
CHECK(v.contains("a"));
|
||||
CHECK(v.value("a", 0) == 1);
|
||||
CHECK(v.materialize()["a"] == 3); // materialize() keeps the last value, unlike the lookups
|
||||
@@ -1248,6 +1254,25 @@ void from_json(const json& j, record& r)
|
||||
j.at("name").get_to(r.name);
|
||||
j.at("count").get_to(r.count);
|
||||
}
|
||||
|
||||
struct defaults
|
||||
{
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
};
|
||||
|
||||
// sets only the members the JSON value has
|
||||
void from_json(const json& j, defaults& d)
|
||||
{
|
||||
if (j.contains("a"))
|
||||
{
|
||||
j.at("a").get_to(d.a);
|
||||
}
|
||||
if (j.contains("b"))
|
||||
{
|
||||
j.at("b").get_to(d.b);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("json_view values")
|
||||
@@ -1369,6 +1394,14 @@ TEST_CASE("json_view values")
|
||||
CHECK(name == "widget");
|
||||
CHECK(count == 3);
|
||||
|
||||
// other types go to from_json with the existing value, as basic_json::get_to()
|
||||
defaults def;
|
||||
def.b = 5;
|
||||
const json_document partial = json_document::parse(R"({"a":4})");
|
||||
partial.root().get_to(def);
|
||||
CHECK(def.a == 4);
|
||||
CHECK(def.b == 5);
|
||||
|
||||
// a duplicate key: the last value, as parse()
|
||||
const json_document dup = json_document::parse(R"({"a":1,"a":2})");
|
||||
CHECK((dup.root().get<std::map<std::string, int>>() == std::map<std::string, int> {{"a", 2}}));
|
||||
|
||||
Reference in new issue
Block a user