}
}
+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;
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 {};
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>();
}
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.");
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 {
std::string serialize() const override
{
- return "\"" + data + "\"";
+ return "\"" + this->data + "\"";
}
void deserialize(const std::string& dumped) override
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