changeset 488:b280d7aca160

Json: add typed valueOr for objects and arrays
author David Demelier <markand@malikania.fr>
date Fri, 13 Nov 2015 19:53:38 +0100
parents d061bad36315
children 4376ec6e5329
files cmake/CodeFunctions.cmake modules/json/json.h modules/json/test/main.cpp
diffstat 3 files changed, 81 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/cmake/CodeFunctions.cmake	Fri Nov 13 09:50:52 2015 +0100
+++ b/cmake/CodeFunctions.cmake	Fri Nov 13 19:53:38 2015 +0100
@@ -47,13 +47,13 @@
 			# Finally create the executable and the test
 			#
 			add_executable(test-${MOD_NAME} ${MOD_SOURCES} ${MOD_RESOURCES} ${MAIN})
-	
+
 			add_test(
 				NAME ${MOD_NAME}
 				COMMAND test-${MOD_NAME}
 				WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
 			)
-	
+
 			set_target_properties(
 				test-${MOD_NAME}
 				PROPERTIES
--- a/modules/json/json.h	Fri Nov 13 09:50:52 2015 +0100
+++ b/modules/json/json.h	Fri Nov 13 19:53:38 2015 +0100
@@ -784,6 +784,24 @@
 	}
 
 	/**
+	 * Overloaded function with type check.
+	 *
+	 * @param position the position
+	 * @param type the requested type
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	inline Value valueOr(unsigned position, Type type, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Array || position >= m_array.size() || m_array[position].typeOf() != type) {
+			return defaultValue;
+		}
+
+		return m_array[position];
+	}
+
+	/**
 	 * Get a value at the specified index.
 	 *
 	 * @pre must be an array
@@ -973,6 +991,30 @@
 	}
 
 	/**
+	 * Overloaded function with type check.
+	 *
+	 * @param name the name
+	 * @param type the requested type
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	Value valueOr(const std::string &name, Type type, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Object) {
+			return defaultValue;
+		}
+
+		auto it = m_object.find(name);
+
+		if (it == m_object.end() || it->second.typeOf() != type) {
+			return defaultValue;
+		}
+
+		return it->second;
+	}
+
+	/**
 	 * Get a value from the object.
 	 *
 	 * @pre must be an object
@@ -1017,20 +1059,6 @@
 	}
 
 	/**
-	 * Get a value from the object.
-	 *
-	 * @pre must be an object
-	 * @param name the value key
-	 * @return the value
-	 */
-	inline const Value &operator[](const std::string &name) const
-	{
-		assert(isObject());
-
-		return m_object.at(name);
-	}
-
-	/**
 	 * Find a value by key.
 	 *
 	 * @pre must be an object
--- a/modules/json/test/main.cpp	Fri Nov 13 09:50:52 2015 +0100
+++ b/modules/json/test/main.cpp	Fri Nov 13 19:53:38 2015 +0100
@@ -220,18 +220,28 @@
 
 TEST(Object, valueOr)
 {
-	try {
-		json::Value object = json::object({
-			{ "x", 10 },
-			{ "y", 20 }
-		});
+	json::Value object = json::object({
+		{ "x", 10 },
+		{ "y", 20 }
+	});
+
+	ASSERT_EQ(10, object.valueOr("x", -9999).toInt());
+	ASSERT_EQ(20, object.valueOr("y", -9999).toInt());
+	ASSERT_EQ(-9999, object.valueOr("not-found", -9999).toInt());
+}
 
-		ASSERT_EQ(10, object.valueOr("x", -9999).toInt());
-		ASSERT_EQ(20, object.valueOr("y", -9999).toInt());
-		ASSERT_EQ(-9999, object.valueOr("not-found", -9999).toInt());
-	} catch (const json::Error &ex) {
-		FAIL() << ex.what();
-	}
+TEST(Object, valueOr2)
+{
+	json::Value object = json::object({
+		{ "x", 10 },
+		{ "y", 20 }
+	});
+
+	ASSERT_EQ(10, object.valueOr("x", json::Type::Int, -9999).toInt());
+	ASSERT_EQ(20, object.valueOr("y", json::Type::Int, -9999).toInt());
+	ASSERT_EQ(-9999, object.valueOr("x", json::Type::String, -9999).toInt());
+	ASSERT_EQ(-9999, object.valueOr("y", json::Type::Boolean, -9999).toInt());
+	ASSERT_EQ(-9999, object.valueOr("not-found", -9999).toInt());
 }
 
 TEST(ObjectInitializer, simple)
@@ -269,7 +279,7 @@
 		ASSERT_EQ(99, object["age"].toInt());
 
 		// Second
-		const json::Value &network = object["network"];
+		json::Value network = object["network"];
 		ASSERT_TRUE(network.isObject());
 		ASSERT_EQ(2, static_cast<int>(network.size()));
 		ASSERT_EQ(9999, network["port"].toInt());
@@ -393,6 +403,21 @@
 	}
 }
 
+TEST(Array, valueOr2)
+{
+	try {
+		json::Value array = json::array({-10, -20});
+
+		ASSERT_EQ(-10, array.valueOr(0, json::Type::Int, -9999).toInt());
+		ASSERT_EQ(-20, array.valueOr(1, json::Type::Int, -9999).toInt());
+		ASSERT_EQ(-9999, array.valueOr(0, json::Type::String, -9999).toInt());
+		ASSERT_EQ(-9999, array.valueOr(1, json::Type::Boolean, -9999).toInt());
+		ASSERT_EQ(-9999, array.valueOr(2, -9999).toInt());
+	} catch (const json::Error &ex) {
+		FAIL() << ex.what();
+	}
+}
+
 TEST(ArrayInitializer, simple)
 {
 	try {