Commit 463fe25adc9402828bd029a9bf8da8da4fb18a3c

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent e9c64111

Add safeGetMember function to get a json member or null.

hueplusplus/Hue.cpp
@@ -37,6 +37,7 @@ @@ -37,6 +37,7 @@
37 #include "include/SimpleColorHueStrategy.h" 37 #include "include/SimpleColorHueStrategy.h"
38 #include "include/SimpleColorTemperatureStrategy.h" 38 #include "include/SimpleColorTemperatureStrategy.h"
39 #include "include/UPnP.h" 39 #include "include/UPnP.h"
  40 +#include "include/Utils.h"
40 41
41 HueFinder::HueFinder(std::shared_ptr<const IHttpHandler> handler) : http_handler(std::move(handler)) {} 42 HueFinder::HueFinder(std::shared_ptr<const IHttpHandler> handler) : http_handler(std::move(handler)) {}
42 43
@@ -180,10 +181,11 @@ std::string Hue::requestUsername(const std::string&amp; ip) @@ -180,10 +181,11 @@ std::string Hue::requestUsername(const std::string&amp; ip)
180 181
181 if (answer.size() > 0) 182 if (answer.size() > 0)
182 { 183 {
183 - if (answer[0].count("success")) 184 + nlohmann::json jsonUser = utils::safeGetMember(answer, 0, "success", "username");
  185 + if (jsonUser != nullptr)
184 { 186 {
185 // [{"success":{"username": "<username>"}}] 187 // [{"success":{"username": "<username>"}}]
186 - username = answer[0]["success"]["username"]; 188 + username = jsonUser;
187 this->ip = ip; 189 this->ip = ip;
188 // Update commands with new username and ip 190 // Update commands with new username and ip
189 commands = HueCommandAPI(ip, port, username, http_handler); 191 commands = HueCommandAPI(ip, port, username, http_handler);
@@ -290,8 +292,7 @@ HueLight&amp; Hue::getLight(int id) @@ -290,8 +292,7 @@ HueLight&amp; Hue::getLight(int id)
290 bool Hue::removeLight(int id) 292 bool Hue::removeLight(int id)
291 { 293 {
292 nlohmann::json result = commands.DELETERequest("/lights/" + std::to_string(id), nlohmann::json::object()); 294 nlohmann::json result = commands.DELETERequest("/lights/" + std::to_string(id), nlohmann::json::object());
293 - bool success = result.is_array() && result.size() > 0 && result[0].count("success")  
294 - && result[0]["success"] == "/lights/" + std::to_string(id) + " deleted"; 295 + bool success = utils::safeGetMember(result, 0, "success") == "/lights/" + std::to_string(id) + " deleted";
295 if (success && lights.count(id) != 0) 296 if (success && lights.count(id) != 0)
296 { 297 {
297 lights.erase(id); 298 lights.erase(id);
hueplusplus/HueLight.cpp
@@ -132,8 +132,7 @@ bool HueLight::setName(const std::string&amp; name) @@ -132,8 +132,7 @@ bool HueLight::setName(const std::string&amp; name)
132 nlohmann::json reply = SendPutRequest(request, "/name"); 132 nlohmann::json reply = SendPutRequest(request, "/name");
133 133
134 // Check whether request was successful 134 // Check whether request was successful
135 - return reply.size() > 0 && reply[0].count("success")  
136 - && reply[0]["success"]["/lights/" + std::to_string(id) + "/name"] == name; 135 + return utils::safeGetMember(reply, 0, "success", "/lights/" + std::to_string(id) + "/name") == name;
137 } 136 }
138 137
139 ColorType HueLight::getColorType() const 138 ColorType HueLight::getColorType() const
@@ -235,7 +234,7 @@ void HueLight::refreshState() @@ -235,7 +234,7 @@ void HueLight::refreshState()
235 // std::chrono::steady_clock::now(); std::cout << "\tRefreshing lampstate of 234 // std::chrono::steady_clock::now(); std::cout << "\tRefreshing lampstate of
236 // lamp with id: " << id << ", ip: " << ip << "\n"; 235 // lamp with id: " << id << ", ip: " << ip << "\n";
237 nlohmann::json answer = commands.GETRequest("/lights/" + std::to_string(id), nlohmann::json::object()); 236 nlohmann::json answer = commands.GETRequest("/lights/" + std::to_string(id), nlohmann::json::object());
238 - if (answer.is_object() && answer.count("state")) 237 + if (answer.count("state"))
239 { 238 {
240 state = answer; 239 state = answer;
241 } 240 }
hueplusplus/Utils.cpp
@@ -26,25 +26,25 @@ @@ -26,25 +26,25 @@
26 26
27 namespace utils 27 namespace utils
28 { 28 {
29 - bool validateReplyForLight(nlohmann::json request, nlohmann::json reply, int lightId) 29 + bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& reply, int lightId)
30 { 30 {
31 bool success = false; 31 bool success = false;
32 std::string path = "/lights/" + std::to_string(lightId) + "/state/"; 32 std::string path = "/lights/" + std::to_string(lightId) + "/state/";
33 - for (nlohmann::json::iterator it = reply.begin(); it != reply.end(); ++it) 33 + for (auto it = reply.begin(); it != reply.end(); ++it)
34 { 34 {
35 success = it.value().count("success"); 35 success = it.value().count("success");
36 if (success) 36 if (success)
37 { 37 {
38 // Traverse through first object 38 // Traverse through first object
39 nlohmann::json successObject = it.value()["success"]; 39 nlohmann::json successObject = it.value()["success"];
40 - for (nlohmann::json::iterator successIt = successObject.begin(); successIt != successObject.end(); 40 + for (auto successIt = successObject.begin(); successIt != successObject.end();
41 ++successIt) 41 ++successIt)
42 { 42 {
43 const std::string successPath = successIt.key(); 43 const std::string successPath = successIt.key();
44 if (successPath.find(path) == 0) 44 if (successPath.find(path) == 0)
45 { 45 {
46 const std::string valueKey = successPath.substr(path.size()); 46 const std::string valueKey = successPath.substr(path.size());
47 - nlohmann::json::iterator requestIt = request.find(valueKey); 47 + auto requestIt = request.find(valueKey);
48 success = requestIt != request.end(); 48 success = requestIt != request.end();
49 if (success) 49 if (success)
50 { 50 {
hueplusplus/include/Utils.h
@@ -30,7 +30,33 @@ namespace utils @@ -30,7 +30,33 @@ namespace utils
30 //! \param reply The reply that was received 30 //! \param reply The reply that was received
31 //! \param lightId The identifier of the light 31 //! \param lightId The identifier of the light
32 //! \return True if request was executed correctly 32 //! \return True if request was executed correctly
33 - bool validateReplyForLight(nlohmann::json request, nlohmann::json reply, int lightId); 33 + bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& reply, int lightId);
  34 +
  35 + //! \brief Returns the object/array member or null if it does not exist
  36 + template<typename... Paths>
  37 + nlohmann::json safeGetMember(const nlohmann::json& json, std::size_t index, Paths&&... otherPaths)
  38 + {
  39 + if (!json.is_array() || json.size() <= index)
  40 + {
  41 + return nullptr;
  42 + }
  43 + return safeGetMember(json[index], std::forward<Paths>(otherPaths)...);
  44 + }
  45 + template<typename KeyT, typename... Paths,
  46 + std::enable_if_t<!std::is_integral<std::remove_reference_t<KeyT>>::value>* = nullptr>
  47 + nlohmann::json safeGetMember(const nlohmann::json& json, KeyT&& key, Paths&&... otherPaths)
  48 + {
  49 + auto memberIt = json.find(std::forward<KeyT>(key));
  50 + if (memberIt == json.end())
  51 + {
  52 + return nullptr;
  53 + }
  54 + return safeGetMember(*memberIt, std::forward<Paths>(otherPaths)...);
  55 + }
  56 + inline nlohmann::json safeGetMember(const nlohmann::json& json)
  57 + {
  58 + return json;
  59 + }
34 } // namespace utils 60 } // namespace utils
35 61
36 #endif 62 #endif
37 \ No newline at end of file 63 \ No newline at end of file