cannam@150: #include cannam@150: #include cannam@150: #include cannam@150: #include cannam@150: #include cannam@150: #include "json11.hpp" cannam@150: #include cannam@150: #include cannam@150: #include cannam@150: #include cannam@150: cannam@150: using namespace json11; cannam@150: using std::string; cannam@150: cannam@150: // Check that Json has the properties we want. cannam@150: #include cannam@150: #define CHECK_TRAIT(x) static_assert(std::x::value, #x) cannam@150: CHECK_TRAIT(is_nothrow_constructible); cannam@150: CHECK_TRAIT(is_nothrow_default_constructible); cannam@150: CHECK_TRAIT(is_copy_constructible); cannam@150: CHECK_TRAIT(is_nothrow_move_constructible); cannam@150: CHECK_TRAIT(is_copy_assignable); cannam@150: CHECK_TRAIT(is_nothrow_move_assignable); cannam@150: CHECK_TRAIT(is_nothrow_destructible); cannam@150: cannam@150: void parse_from_stdin() { cannam@150: string buf; cannam@150: string line; cannam@150: while (std::getline(std::cin, line)) { cannam@150: buf += line + "\n"; cannam@150: } cannam@150: cannam@150: string err; cannam@150: auto json = Json::parse(buf, err); cannam@150: if (!err.empty()) { cannam@150: printf("Failed: %s\n", err.c_str()); cannam@150: } else { cannam@150: printf("Result: %s\n", json.dump().c_str()); cannam@150: } cannam@150: } cannam@150: cannam@150: int main(int argc, char **argv) { cannam@150: if (argc == 2 && argv[1] == string("--stdin")) { cannam@150: parse_from_stdin(); cannam@150: return 0; cannam@150: } cannam@150: cannam@150: const string simple_test = cannam@150: R"({"k1":"v1", "k2":42, "k3":["a",123,true,false,null]})"; cannam@150: cannam@150: string err; cannam@150: auto json = Json::parse(simple_test, err); cannam@150: cannam@150: std::cout << "k1: " << json["k1"].string_value() << "\n"; cannam@150: std::cout << "k3: " << json["k3"].dump() << "\n"; cannam@150: cannam@150: for (auto &k : json["k3"].array_items()) { cannam@150: std::cout << " - " << k.dump() << "\n"; cannam@150: } cannam@150: cannam@150: const string comment_test = R"({ cannam@150: // comment /* with nested comment */ cannam@150: "a": 1, cannam@150: // comment cannam@150: // continued cannam@150: "b": "text", cannam@150: /* multi cannam@150: line cannam@150: comment */ cannam@150: // and single-line comment cannam@150: "c": [1, 2, 3] cannam@150: })"; cannam@150: cannam@150: string err_comment; cannam@150: auto json_comment = Json::parse( cannam@150: comment_test, err_comment, JsonParse::COMMENTS); cannam@150: if (!err_comment.empty()) { cannam@150: printf("Failed: %s\n", err_comment.c_str()); cannam@150: } else { cannam@150: printf("Result: %s\n", json_comment.dump().c_str()); cannam@150: } cannam@150: cannam@150: string failing_comment_test = R"({ cannam@150: /* bad comment cannam@150: "a": 1, cannam@150: })"; cannam@150: cannam@150: string err_failing_comment; cannam@150: auto json_failing_comment = Json::parse( cannam@150: failing_comment_test, err_failing_comment, JsonParse::COMMENTS); cannam@150: if (!err_failing_comment.empty()) { cannam@150: printf("Failed: %s\n", err_failing_comment.c_str()); cannam@150: } else { cannam@150: printf("Result: %s\n", json_failing_comment.dump().c_str()); cannam@150: } cannam@150: cannam@150: failing_comment_test = R"({ cannam@150: / / bad comment })"; cannam@150: cannam@150: json_failing_comment = Json::parse( cannam@150: failing_comment_test, err_failing_comment, JsonParse::COMMENTS); cannam@150: if (!err_failing_comment.empty()) { cannam@150: printf("Failed: %s\n", err_failing_comment.c_str()); cannam@150: } else { cannam@150: printf("Result: %s\n", json_failing_comment.dump().c_str()); cannam@150: } cannam@150: cannam@150: failing_comment_test = R"({// bad comment })"; cannam@150: cannam@150: json_failing_comment = Json::parse( cannam@150: failing_comment_test, err_failing_comment, JsonParse::COMMENTS); cannam@150: if (!err_failing_comment.empty()) { cannam@150: printf("Failed: %s\n", err_failing_comment.c_str()); cannam@150: } else { cannam@150: printf("Result: %s\n", json_failing_comment.dump().c_str()); cannam@150: } cannam@150: cannam@150: failing_comment_test = R"({ cannam@150: "a": 1 cannam@150: }/)"; cannam@150: cannam@150: json_failing_comment = Json::parse( cannam@150: failing_comment_test, err_failing_comment, JsonParse::COMMENTS); cannam@150: if (!err_failing_comment.empty()) { cannam@150: printf("Failed: %s\n", err_failing_comment.c_str()); cannam@150: } else { cannam@150: printf("Result: %s\n", json_failing_comment.dump().c_str()); cannam@150: } cannam@150: cannam@150: failing_comment_test = R"({/* bad cannam@150: comment *})"; cannam@150: cannam@150: json_failing_comment = Json::parse( cannam@150: failing_comment_test, err_failing_comment, JsonParse::COMMENTS); cannam@150: if (!err_failing_comment.empty()) { cannam@150: printf("Failed: %s\n", err_failing_comment.c_str()); cannam@150: } else { cannam@150: printf("Result: %s\n", json_failing_comment.dump().c_str()); cannam@150: } cannam@150: cannam@150: std::list l1 { 1, 2, 3 }; cannam@150: std::vector l2 { 1, 2, 3 }; cannam@150: std::set l3 { 1, 2, 3 }; cannam@150: assert(Json(l1) == Json(l2)); cannam@150: assert(Json(l2) == Json(l3)); cannam@150: cannam@150: std::map m1 { { "k1", "v1" }, { "k2", "v2" } }; cannam@150: std::unordered_map m2 { { "k1", "v1" }, { "k2", "v2" } }; cannam@150: assert(Json(m1) == Json(m2)); cannam@150: cannam@150: // Json literals cannam@150: Json obj = Json::object({ cannam@150: { "k1", "v1" }, cannam@150: { "k2", 42.0 }, cannam@150: { "k3", Json::array({ "a", 123.0, true, false, nullptr }) }, cannam@150: }); cannam@150: cannam@150: std::cout << "obj: " << obj.dump() << "\n"; cannam@150: cannam@150: assert(Json("a").number_value() == 0); cannam@150: assert(Json("a").string_value() == "a"); cannam@150: assert(Json().number_value() == 0); cannam@150: cannam@150: assert(obj == json); cannam@150: assert(Json(42) == Json(42.0)); cannam@150: assert(Json(42) != Json(42.1)); cannam@150: cannam@150: const string unicode_escape_test = cannam@150: R"([ "blah\ud83d\udca9blah\ud83dblah\udca9blah\u0000blah\u1234" ])"; cannam@150: cannam@150: const char utf8[] = "blah" "\xf0\x9f\x92\xa9" "blah" "\xed\xa0\xbd" "blah" cannam@150: "\xed\xb2\xa9" "blah" "\0" "blah" "\xe1\x88\xb4"; cannam@150: cannam@150: Json uni = Json::parse(unicode_escape_test, err); cannam@150: assert(uni[0].string_value().size() == (sizeof utf8) - 1); cannam@150: assert(std::memcmp(uni[0].string_value().data(), utf8, sizeof utf8) == 0); cannam@150: cannam@150: // Demonstrates the behavior change in Xcode 7 / Clang 3.7 described cannam@150: // here: https://llvm.org/bugs/show_bug.cgi?id=23812 cannam@150: Json nested_array = Json::array { Json::array { 1, 2, 3 } }; cannam@150: assert(nested_array.is_array()); cannam@150: assert(nested_array.array_items().size() == 1); cannam@150: assert(nested_array.array_items()[0].is_array()); cannam@150: assert(nested_array.array_items()[0].array_items().size() == 3); cannam@150: cannam@150: Json my_json = Json::object { cannam@150: { "key1", "value1" }, cannam@150: { "key2", false }, cannam@150: { "key3", Json::array { 1, 2, 3 } }, cannam@150: }; cannam@150: std::string json_str = my_json.dump(); cannam@150: printf("%s\n", json_str.c_str()); cannam@150: cannam@150: class Point { cannam@150: public: cannam@150: int x; cannam@150: int y; cannam@150: Point (int x, int y) : x(x), y(y) {} cannam@150: Json to_json() const { return Json::array { x, y }; } cannam@150: }; cannam@150: cannam@150: std::vector points = { { 1, 2 }, { 10, 20 }, { 100, 200 } }; cannam@150: std::string points_json = Json(points).dump(); cannam@150: printf("%s\n", points_json.c_str()); cannam@150: }