Added Value::findType with String key (#1574)
This adds a convenience function to return a member if it has a specific
json type. All isType values are supported.
Co-authored-by: Jordan Bayles <bayles.jordan@gmail.com>
diff --git a/include/json/value.h b/include/json/value.h
index 3074932..5f65443 100644
--- a/include/json/value.h
+++ b/include/json/value.h
@@ -549,6 +549,29 @@
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
Value const* find(const String& key) const;
+
+ /// Calls find and only returns a valid pointer if the type is found
+ template <typename T, bool (T::*TMemFn)() const>
+ Value const* findValue(const String& key) const {
+ Value const* found = find(key);
+ if (!found || !(found->*TMemFn)())
+ return nullptr;
+ return found;
+ }
+
+ Value const* findNull(const String& key) const;
+ Value const* findBool(const String& key) const;
+ Value const* findInt(const String& key) const;
+ Value const* findInt64(const String& key) const;
+ Value const* findUInt(const String& key) const;
+ Value const* findUInt64(const String& key) const;
+ Value const* findIntegral(const String& key) const;
+ Value const* findDouble(const String& key) const;
+ Value const* findNumeric(const String& key) const;
+ Value const* findString(const String& key) const;
+ Value const* findArray(const String& key) const;
+ Value const* findObject(const String& key) const;
+
/// Most general and efficient version of object-mutators.
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
index 527d716..a875d28 100644
--- a/src/lib_json/json_value.cpp
+++ b/src/lib_json/json_value.cpp
@@ -1129,6 +1129,44 @@
Value const* Value::find(const String& key) const {
return find(key.data(), key.data() + key.length());
}
+
+Value const* Value::findNull(const String& key) const {
+ return findValue<Value, &Value::isNull>(key);
+}
+Value const* Value::findBool(const String& key) const {
+ return findValue<Value, &Value::isBool>(key);
+}
+Value const* Value::findInt(const String& key) const {
+ return findValue<Value, &Value::isInt>(key);
+}
+Value const* Value::findInt64(const String& key) const {
+ return findValue<Value, &Value::isInt64>(key);
+}
+Value const* Value::findUInt(const String& key) const {
+ return findValue<Value, &Value::isUInt>(key);
+}
+Value const* Value::findUInt64(const String& key) const {
+ return findValue<Value, &Value::isUInt64>(key);
+}
+Value const* Value::findIntegral(const String& key) const {
+ return findValue<Value, &Value::isIntegral>(key);
+}
+Value const* Value::findDouble(const String& key) const {
+ return findValue<Value, &Value::isDouble>(key);
+}
+Value const* Value::findNumeric(const String& key) const {
+ return findValue<Value, &Value::isNumeric>(key);
+}
+Value const* Value::findString(const String& key) const {
+ return findValue<Value, &Value::isString>(key);
+}
+Value const* Value::findArray(const String& key) const {
+ return findValue<Value, &Value::isArray>(key);
+}
+Value const* Value::findObject(const String& key) const {
+ return findValue<Value, &Value::isObject>(key);
+}
+
Value* Value::demand(char const* begin, char const* end) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
"in Json::Value::demand(begin, end): requires "
diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp
index 5a0ce01..60f149d 100644
--- a/src/test_lib_json/main.cpp
+++ b/src/test_lib_json/main.cpp
@@ -76,6 +76,8 @@
Json::Value float_{0.00390625f};
Json::Value array1_;
Json::Value object1_;
+ Json::Value object2_;
+ Json::Value object3_;
Json::Value emptyString_{""};
Json::Value string1_{"a"};
Json::Value string_{"sometext with space"};
@@ -85,6 +87,34 @@
ValueTest() {
array1_.append(1234);
object1_["id"] = 1234;
+
+ // object2 with matching values
+ object2_["null"] = Json::nullValue;
+ object2_["bool"] = true;
+ object2_["int"] = Json::Int{Json::Value::maxInt};
+ object2_["int64"] = Json::Int64{Json::Value::maxInt64};
+ object2_["uint"] = Json::UInt{Json::Value::maxUInt};
+ object2_["uint64"] = Json::UInt64{Json::Value::maxUInt64};
+ object2_["integral"] = 1234;
+ object2_["double"] = 1234.56789;
+ object2_["numeric"] = 0.12345f;
+ object2_["string"] = "string";
+ object2_["array"] = Json::arrayValue;
+ object2_["object"] = Json::objectValue;
+
+ // object3 with not matching values
+ object3_["object"] = Json::nullValue;
+ object3_["null"] = true;
+ object3_["bool"] = Json::Int{Json::Value::maxInt};
+ object3_["int"] = "not_an_int";
+ object3_["int64"] = "not_an_int64";
+ object3_["uint"] = "not_an_uint";
+ object3_["uin64"] = "not_an_uint64";
+ object3_["integral"] = 1234.56789;
+ object3_["double"] = false;
+ object3_["numeric"] = "string";
+ object3_["string"] = Json::arrayValue;
+ object3_["array"] = Json::objectValue;
}
struct IsCheck {
@@ -234,6 +264,62 @@
const Json::Value* stringFoundUnknownId = object1_.find(stringUnknownIdKey);
JSONTEST_ASSERT_EQUAL(nullptr, stringFoundUnknownId);
+ // Access through find<Type>()
+ const Json::Value* nullFound = object2_.findNull("null");
+ JSONTEST_ASSERT(nullFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(Json::nullValue, *nullFound);
+ JSONTEST_ASSERT(object3_.findNull("null") == nullptr);
+
+ const Json::Value* boolFound = object2_.findBool("bool");
+ JSONTEST_ASSERT(boolFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(true, *boolFound);
+ JSONTEST_ASSERT(object3_.findBool("bool") == nullptr);
+
+ const Json::Value* intFound = object2_.findInt("int");
+ JSONTEST_ASSERT(intFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(Json::Int{Json::Value::maxInt}, *intFound);
+ JSONTEST_ASSERT(object3_.findInt("int") == nullptr);
+
+ const Json::Value* int64Found = object2_.findInt64("int64");
+ JSONTEST_ASSERT(int64Found != nullptr);
+ JSONTEST_ASSERT_EQUAL(Json::Int64{Json::Value::maxInt64}, *int64Found);
+ JSONTEST_ASSERT(object3_.findInt64("int64") == nullptr);
+
+ const Json::Value* uintFound = object2_.findUInt("uint");
+ JSONTEST_ASSERT(uintFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(Json::UInt{Json::Value::maxUInt}, *uintFound);
+ JSONTEST_ASSERT(object3_.findUInt("uint") == nullptr);
+
+ const Json::Value* uint64Found = object2_.findUInt64("uint64");
+ JSONTEST_ASSERT(uint64Found != nullptr);
+ JSONTEST_ASSERT_EQUAL(Json::UInt64{Json::Value::maxUInt64}, *uint64Found);
+ JSONTEST_ASSERT(object3_.findUInt64("uint64") == nullptr);
+
+ const Json::Value* integralFound = object2_.findIntegral("integral");
+ JSONTEST_ASSERT(integralFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(1234, *integralFound);
+ JSONTEST_ASSERT(object3_.findIntegral("integral") == nullptr);
+
+ const Json::Value* doubleFound = object2_.findDouble("double");
+ JSONTEST_ASSERT(doubleFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(1234.56789, *doubleFound);
+ JSONTEST_ASSERT(object3_.findDouble("double") == nullptr);
+
+ const Json::Value* numericFound = object2_.findNumeric("numeric");
+ JSONTEST_ASSERT(numericFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(0.12345f, *numericFound);
+ JSONTEST_ASSERT(object3_.findNumeric("numeric") == nullptr);
+
+ const Json::Value* stringFound = object2_.findString("string");
+ JSONTEST_ASSERT(stringFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(std::string{"string"}, *stringFound);
+ JSONTEST_ASSERT(object3_.findString("string") == nullptr);
+
+ const Json::Value* arrayFound = object2_.findArray("array");
+ JSONTEST_ASSERT(arrayFound != nullptr);
+ JSONTEST_ASSERT_EQUAL(Json::arrayValue, *arrayFound);
+ JSONTEST_ASSERT(object3_.findArray("array") == nullptr);
+
// Access through demand()
const char yetAnotherIdKey[] = "yet another id";
const Json::Value* foundYetAnotherId =