// // json_binder_object.t.h // json // // Created by Sam Jaffe on 2/27/17. // #include #include "json/json_binder.hpp" using namespace json::binder; using namespace json::parser; using vec_t = std::vector; using map_t = std::map; struct TestObject { int count; double average; map_t data; }; bool operator==(TestObject const & lhs, TestObject const & rhs) { return lhs.count == rhs.count && lhs.average == rhs.average && lhs.data == rhs.data; } class JsonBinderObjectTest : public ::testing::Test { protected: static object_binder & GetBinder() { static object_binder val = object_binder() ("count", &TestObject::count) ("average", &TestObject::average) ("data", direct_binder(&TestObject::data)); return val; } }; TEST_F(JsonBinderObjectTest, ParsesSuccessfully) { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }}"; TestObject out = { 0, 0.0, {} }; TestObject expected = { 10, 1.0, {{"key1", {1, 2}},{"key2", {3, 4}}} }; EXPECT_NO_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all)); EXPECT_THAT(out, expected); } TEST_F(JsonBinderObjectTest, IgnoresUnknownKeysByDefault) { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":true}"; TestObject out = { 0, 0.0, {} }; TestObject expected = { 10, 1.0, {{"key1", {1, 2}},{"key2", {3, 4}}} }; EXPECT_NO_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all)); EXPECT_THAT(out, expected); } TEST_F(JsonBinderObjectTest, ThrowsOnUnknownKeyWithSetting) { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":true}"; TestObject out = { 0, 0.0, {} }; EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, disable_unknown_keys), json::malformed_json_exception); } TEST_F(JsonBinderObjectTest, AllowsMissingExpectedKeysByDefault) { char data[] = "{ \"count\":10, \"average\":1.0 }"; TestObject out = { 0, 0.0, {} }; TestObject expected = { 10, 1.0, {} }; EXPECT_NO_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all)); EXPECT_THAT(out, expected); } TEST_F(JsonBinderObjectTest, ThrowsOnMissingExpectedKeyWithSetting) { char data[] = "{ \"count\":10, \"average\":1.0 }"; TestObject out = { 0, 0.0, {} }; EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, disable_missing_keys), json::malformed_json_exception); } TEST_F(JsonBinderObjectTest, ThrowsOnMissingStartToken) { char data[] = "\"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] } }"; TestObject out = { 0, 0.0, {} }; EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all), json::malformed_json_exception); } TEST_F(JsonBinderObjectTest, ThrowsIfMissingValueForKey) { char data[] = "{ \"count\":10, \"average\":1.0, \"data\": }"; TestObject out = { 0, 0.0, {} }; EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all), json::malformed_json_exception); } TEST_F(JsonBinderObjectTest, ThrowsOnMissingEndToken) { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }"; TestObject out = { 0, 0.0, {} }; EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all), json::unterminated_json_exception); } TEST_F(JsonBinderObjectTest, ThrowsOnMissingValueForKeyEvenForUnknownKey) { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":{\"key\": } }"; TestObject out = { 0, 0.0, {} }; EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all), json::malformed_json_exception); } TEST_F(JsonBinderObjectTest, ThrowsOnMissingEndTokenEvenForUnknownKey) { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":[1.0 }"; TestObject out = { 0, 0.0, {} }; EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all), json::unterminated_json_exception); } TEST_F(JsonBinderObjectTest, ThrowsOnMissingEndTokenEvenForUnknownKey2) { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":{\"key\":false }"; TestObject out = { 0, 0.0, {} }; EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all), json::unterminated_json_exception); } std::string ify(double value) { std::stringstream ss; ss << std::fixed << value; return ss.str(); } TEST_F(JsonBinderObjectTest, WritesBackOriginalObject) { std::string const dbl = ify(1.0); std::string const expected = "{\"average\":"+dbl+",\"count\":10,\"data\":{\"key1\":[1,2],\"key2\":[3,4]}}"; std::stringstream ss; TestObject const in = { 10, 1.0, { { "key1", {1, 2} }, { "key2", {3, 4} } } }; EXPECT_NO_THROW(write(json::binder::bind(in, GetBinder()), ss)); EXPECT_THAT(ss.str(), expected); }