Add Bool, Null type to JSON
authorSangwan Kwon <sangwan.kwon@samsung.com>
Thu, 14 May 2020 06:43:33 +0000 (15:43 +0900)
committer권상완/Security 2Lab(SR)/Engineer/삼성전자 <sangwan.kwon@samsung.com>
Mon, 18 May 2020 00:52:02 +0000 (09:52 +0900)
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
src/vist/json/json.hpp
src/vist/json/tests/json.cpp
src/vist/json/value.hpp

index 1149179..760ced9 100644 (file)
@@ -17,7 +17,7 @@
  * Usable JSON header-only library.
  *   - Applied design pattern: Composite pattern
  *     - Component structure: Value 
- *     - Leaf structure: Int, String (To be added: Bool, Null)
+ *     - Leaf structure: Int, String, Bool, Null
  *     - Composite structure: Array, Object
  */
 /*
index 4ecd410..4b1e4cd 100644 (file)
@@ -85,6 +85,60 @@ TEST(JsonTests, string_type_mismatch)
        }
 }
 
+TEST(JsonTests, bool)
+{
+       Json json;
+       json["bool"] = true;
+
+       bool value = json["bool"];
+       EXPECT_EQ(value, true);
+       EXPECT_EQ(json["bool"].serialize(), "true");
+
+       json["bool"] = false;
+       value = static_cast<bool>(json["bool"]);
+       EXPECT_EQ(value, false);
+
+       EXPECT_EQ(json["bool"].serialize(), "false");
+
+       json["bool"].deserialize("true");
+       EXPECT_EQ(static_cast<bool>(json["bool"]), true);
+}
+
+TEST(JsonTests, null)
+{
+       Json json;
+       json["null"] = nullptr;
+
+       EXPECT_EQ(json["null"].serialize(), "null");
+}
+
+TEST(JsonTests, type_check)
+{
+       Json json;
+       json["int"] = 1;
+       json["string"] = "string";
+       json["bool"] = true;
+       json["null"] = nullptr;
+       Array array;
+       Object object;
+       json.push("array", array);
+       json.push("object", object);
+
+       EXPECT_TRUE(json["int"].is<Int>());
+       EXPECT_TRUE(json["string"].is<String>());
+       EXPECT_TRUE(json["bool"].is<Bool>());
+       EXPECT_TRUE(json["null"].is<Null>());
+       EXPECT_TRUE(json["array"].is<Array>());
+       EXPECT_TRUE(json["object"].is<Object>());
+
+       EXPECT_FALSE(json["int"].is<String>());
+       EXPECT_FALSE(json["string"].is<Int>());
+       EXPECT_FALSE(json["bool"].is<Int>());
+       EXPECT_FALSE(json["null"].is<Int>());
+       EXPECT_FALSE(json["array"].is<Int>());
+       EXPECT_FALSE(json["object"].is<Int>());
+}
+
 TEST(JsonTests, array)
 {
        Array array;
index 611d98e..04bae16 100644 (file)
 namespace vist {
 namespace json {
 
+struct Bool;
 struct Int;
 struct String;
-struct Object;
+struct Null;
+
 struct Array;
+struct Object;
 
 template<class T> struct dependent_false : std::false_type {};
 
@@ -54,6 +57,9 @@ struct Value {
                        case '{' : this->convert<Object>(); break;
                        case '[' : this->convert<Array>(); break;
                        case '"': this->convert<String>(); break;
+                       case 'n': this->convert<Null>(); break;
+                       case 't': // fall through
+                       case 'f' : this->convert<Bool>(); break;
                        default : this->convert<Int>();
                }
 
@@ -64,10 +70,14 @@ struct Value {
        Value& operator=(const Type& data)
        {
                if constexpr (std::is_same_v<Type, int>)
-                       this->leaf = std::make_shared<Int>(data); 
+                       this->leaf = std::make_shared<Int>(data);
                else if constexpr (std::is_same_v<typename std::decay<Type>::type, std::string> ||
                                                   std::is_same_v<typename std::decay<Type>::type, char*>)
-                       this->leaf = std::make_shared<String>(data); 
+                       this->leaf = std::make_shared<String>(data);
+               else if constexpr (std::is_same_v<Type, bool>)
+                       this->leaf = std::make_shared<Bool>(data);
+               else if constexpr (std::is_same_v<Type, std::nullptr_t>)
+                       this->leaf = std::make_shared<Null>();
                else
                        static_assert(dependent_false<Type>::value, "Not supported type.");
 
@@ -90,7 +100,24 @@ struct Value {
                return (*this->leaf).operator std::string();
        }
 
+       virtual operator bool()
+       {
+               if (auto downcast = std::dynamic_pointer_cast<Bool>(this->leaf); downcast == nullptr)
+                       throw std::runtime_error("Mismatched type.");
+
+               return (*this->leaf).operator bool();
+       }
+
+       template <typename Type>
+       bool is()
+       {
+               auto downcast = std::dynamic_pointer_cast<Type>(this->leaf);
+               return downcast != nullptr;
+       }
+
        std::shared_ptr<Value> leaf;
+
+private:
 };
 
 struct Int : public Value {
@@ -121,7 +148,7 @@ struct String : public Value {
 
        std::string serialize() const override
        {
-               return "\"" + data + "\"";
+               return "\"" + this->data + "\"";
        }
 
        void deserialize(const std::string& dumped) override
@@ -137,11 +164,53 @@ struct String : public Value {
 
        operator std::string() override
        {
-               return data;
+               return this->data;
        }
 
        std::string data;
 };
 
+struct Bool : public Value {
+       explicit Bool() {}
+       explicit Bool(bool data) : data(data) {}
+
+       std::string serialize() const override
+       {
+               return this->data ? "true" : "false";
+       }
+
+       void deserialize(const std::string& dumped) override
+       {
+               if (dumped == "true")
+                       this->data = true;
+               else if (dumped == "false")
+                       this->data = false;
+               else
+                       throw std::invalid_argument("Wrong format.");
+       }
+
+       operator bool() override
+       {
+               return this->data;
+       }
+
+       bool data = false;
+};
+
+struct Null : public Value {
+       explicit Null() {}
+
+       std::string serialize() const override
+       {
+               return "null";
+       }
+
+       void deserialize(const std::string& dumped) override
+       {
+               if (dumped != "null")
+                       throw std::invalid_argument("Wrong format.");
+       }
+};
+
 } // namespace json
 } // namespace vist