Skip to content

Commit ba00447

Browse files
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 <[email protected]>
1 parent 60ccc1f commit ba00447

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

include/json/value.h

+23
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,29 @@ class JSON_API Value {
549549
/// Most general and efficient version of isMember()const, get()const,
550550
/// and operator[]const
551551
Value const* find(const String& key) const;
552+
553+
/// Calls find and only returns a valid pointer if the type is found
554+
template <typename T, bool (T::*TMemFn)() const>
555+
Value const* findValue(const String& key) const {
556+
Value const* found = find(key);
557+
if (!found || !(found->*TMemFn)())
558+
return nullptr;
559+
return found;
560+
}
561+
562+
Value const* findNull(const String& key) const;
563+
Value const* findBool(const String& key) const;
564+
Value const* findInt(const String& key) const;
565+
Value const* findInt64(const String& key) const;
566+
Value const* findUInt(const String& key) const;
567+
Value const* findUInt64(const String& key) const;
568+
Value const* findIntegral(const String& key) const;
569+
Value const* findDouble(const String& key) const;
570+
Value const* findNumeric(const String& key) const;
571+
Value const* findString(const String& key) const;
572+
Value const* findArray(const String& key) const;
573+
Value const* findObject(const String& key) const;
574+
552575
/// Most general and efficient version of object-mutators.
553576
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
554577
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.

src/lib_json/json_value.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,44 @@ Value const* Value::find(char const* begin, char const* end) const {
11291129
Value const* Value::find(const String& key) const {
11301130
return find(key.data(), key.data() + key.length());
11311131
}
1132+
1133+
Value const* Value::findNull(const String& key) const {
1134+
return findValue<Value, &Value::isNull>(key);
1135+
}
1136+
Value const* Value::findBool(const String& key) const {
1137+
return findValue<Value, &Value::isBool>(key);
1138+
}
1139+
Value const* Value::findInt(const String& key) const {
1140+
return findValue<Value, &Value::isInt>(key);
1141+
}
1142+
Value const* Value::findInt64(const String& key) const {
1143+
return findValue<Value, &Value::isInt64>(key);
1144+
}
1145+
Value const* Value::findUInt(const String& key) const {
1146+
return findValue<Value, &Value::isUInt>(key);
1147+
}
1148+
Value const* Value::findUInt64(const String& key) const {
1149+
return findValue<Value, &Value::isUInt64>(key);
1150+
}
1151+
Value const* Value::findIntegral(const String& key) const {
1152+
return findValue<Value, &Value::isIntegral>(key);
1153+
}
1154+
Value const* Value::findDouble(const String& key) const {
1155+
return findValue<Value, &Value::isDouble>(key);
1156+
}
1157+
Value const* Value::findNumeric(const String& key) const {
1158+
return findValue<Value, &Value::isNumeric>(key);
1159+
}
1160+
Value const* Value::findString(const String& key) const {
1161+
return findValue<Value, &Value::isString>(key);
1162+
}
1163+
Value const* Value::findArray(const String& key) const {
1164+
return findValue<Value, &Value::isArray>(key);
1165+
}
1166+
Value const* Value::findObject(const String& key) const {
1167+
return findValue<Value, &Value::isObject>(key);
1168+
}
1169+
11321170
Value* Value::demand(char const* begin, char const* end) {
11331171
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
11341172
"in Json::Value::demand(begin, end): requires "

src/test_lib_json/main.cpp

+86
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ struct ValueTest : JsonTest::TestCase {
7676
Json::Value float_{0.00390625f};
7777
Json::Value array1_;
7878
Json::Value object1_;
79+
Json::Value object2_;
80+
Json::Value object3_;
7981
Json::Value emptyString_{""};
8082
Json::Value string1_{"a"};
8183
Json::Value string_{"sometext with space"};
@@ -85,6 +87,34 @@ struct ValueTest : JsonTest::TestCase {
8587
ValueTest() {
8688
array1_.append(1234);
8789
object1_["id"] = 1234;
90+
91+
// object2 with matching values
92+
object2_["null"] = Json::nullValue;
93+
object2_["bool"] = true;
94+
object2_["int"] = Json::Int{Json::Value::maxInt};
95+
object2_["int64"] = Json::Int64{Json::Value::maxInt64};
96+
object2_["uint"] = Json::UInt{Json::Value::maxUInt};
97+
object2_["uint64"] = Json::UInt64{Json::Value::maxUInt64};
98+
object2_["integral"] = 1234;
99+
object2_["double"] = 1234.56789;
100+
object2_["numeric"] = 0.12345f;
101+
object2_["string"] = "string";
102+
object2_["array"] = Json::arrayValue;
103+
object2_["object"] = Json::objectValue;
104+
105+
// object3 with not matching values
106+
object3_["object"] = Json::nullValue;
107+
object3_["null"] = true;
108+
object3_["bool"] = Json::Int{Json::Value::maxInt};
109+
object3_["int"] = "not_an_int";
110+
object3_["int64"] = "not_an_int64";
111+
object3_["uint"] = "not_an_uint";
112+
object3_["uin64"] = "not_an_uint64";
113+
object3_["integral"] = 1234.56789;
114+
object3_["double"] = false;
115+
object3_["numeric"] = "string";
116+
object3_["string"] = Json::arrayValue;
117+
object3_["array"] = Json::objectValue;
88118
}
89119

90120
struct IsCheck {
@@ -234,6 +264,62 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, objects) {
234264
const Json::Value* stringFoundUnknownId = object1_.find(stringUnknownIdKey);
235265
JSONTEST_ASSERT_EQUAL(nullptr, stringFoundUnknownId);
236266

267+
// Access through find<Type>()
268+
const Json::Value* nullFound = object2_.findNull("null");
269+
JSONTEST_ASSERT(nullFound != nullptr);
270+
JSONTEST_ASSERT_EQUAL(Json::nullValue, *nullFound);
271+
JSONTEST_ASSERT(object3_.findNull("null") == nullptr);
272+
273+
const Json::Value* boolFound = object2_.findBool("bool");
274+
JSONTEST_ASSERT(boolFound != nullptr);
275+
JSONTEST_ASSERT_EQUAL(true, *boolFound);
276+
JSONTEST_ASSERT(object3_.findBool("bool") == nullptr);
277+
278+
const Json::Value* intFound = object2_.findInt("int");
279+
JSONTEST_ASSERT(intFound != nullptr);
280+
JSONTEST_ASSERT_EQUAL(Json::Int{Json::Value::maxInt}, *intFound);
281+
JSONTEST_ASSERT(object3_.findInt("int") == nullptr);
282+
283+
const Json::Value* int64Found = object2_.findInt64("int64");
284+
JSONTEST_ASSERT(int64Found != nullptr);
285+
JSONTEST_ASSERT_EQUAL(Json::Int64{Json::Value::maxInt64}, *int64Found);
286+
JSONTEST_ASSERT(object3_.findInt64("int64") == nullptr);
287+
288+
const Json::Value* uintFound = object2_.findUInt("uint");
289+
JSONTEST_ASSERT(uintFound != nullptr);
290+
JSONTEST_ASSERT_EQUAL(Json::UInt{Json::Value::maxUInt}, *uintFound);
291+
JSONTEST_ASSERT(object3_.findUInt("uint") == nullptr);
292+
293+
const Json::Value* uint64Found = object2_.findUInt64("uint64");
294+
JSONTEST_ASSERT(uint64Found != nullptr);
295+
JSONTEST_ASSERT_EQUAL(Json::UInt64{Json::Value::maxUInt64}, *uint64Found);
296+
JSONTEST_ASSERT(object3_.findUInt64("uint64") == nullptr);
297+
298+
const Json::Value* integralFound = object2_.findIntegral("integral");
299+
JSONTEST_ASSERT(integralFound != nullptr);
300+
JSONTEST_ASSERT_EQUAL(1234, *integralFound);
301+
JSONTEST_ASSERT(object3_.findIntegral("integral") == nullptr);
302+
303+
const Json::Value* doubleFound = object2_.findDouble("double");
304+
JSONTEST_ASSERT(doubleFound != nullptr);
305+
JSONTEST_ASSERT_EQUAL(1234.56789, *doubleFound);
306+
JSONTEST_ASSERT(object3_.findDouble("double") == nullptr);
307+
308+
const Json::Value* numericFound = object2_.findNumeric("numeric");
309+
JSONTEST_ASSERT(numericFound != nullptr);
310+
JSONTEST_ASSERT_EQUAL(0.12345f, *numericFound);
311+
JSONTEST_ASSERT(object3_.findNumeric("numeric") == nullptr);
312+
313+
const Json::Value* stringFound = object2_.findString("string");
314+
JSONTEST_ASSERT(stringFound != nullptr);
315+
JSONTEST_ASSERT_EQUAL(std::string{"string"}, *stringFound);
316+
JSONTEST_ASSERT(object3_.findString("string") == nullptr);
317+
318+
const Json::Value* arrayFound = object2_.findArray("array");
319+
JSONTEST_ASSERT(arrayFound != nullptr);
320+
JSONTEST_ASSERT_EQUAL(Json::arrayValue, *arrayFound);
321+
JSONTEST_ASSERT(object3_.findArray("array") == nullptr);
322+
237323
// Access through demand()
238324
const char yetAnotherIdKey[] = "yet another id";
239325
const Json::Value* foundYetAnotherId =

0 commit comments

Comments
 (0)