cannam@150
|
1 #include <string>
|
cannam@150
|
2 #include <cstdio>
|
cannam@150
|
3 #include <cstring>
|
cannam@150
|
4 #include <iostream>
|
cannam@150
|
5 #include <sstream>
|
cannam@150
|
6 #include "json11.hpp"
|
cannam@150
|
7 #include <cassert>
|
cannam@150
|
8 #include <list>
|
cannam@150
|
9 #include <set>
|
cannam@150
|
10 #include <unordered_map>
|
cannam@150
|
11
|
cannam@150
|
12 using namespace json11;
|
cannam@150
|
13 using std::string;
|
cannam@150
|
14
|
cannam@150
|
15 // Check that Json has the properties we want.
|
cannam@150
|
16 #include <type_traits>
|
cannam@150
|
17 #define CHECK_TRAIT(x) static_assert(std::x::value, #x)
|
cannam@150
|
18 CHECK_TRAIT(is_nothrow_constructible<Json>);
|
cannam@150
|
19 CHECK_TRAIT(is_nothrow_default_constructible<Json>);
|
cannam@150
|
20 CHECK_TRAIT(is_copy_constructible<Json>);
|
cannam@150
|
21 CHECK_TRAIT(is_nothrow_move_constructible<Json>);
|
cannam@150
|
22 CHECK_TRAIT(is_copy_assignable<Json>);
|
cannam@150
|
23 CHECK_TRAIT(is_nothrow_move_assignable<Json>);
|
cannam@150
|
24 CHECK_TRAIT(is_nothrow_destructible<Json>);
|
cannam@150
|
25
|
cannam@150
|
26 void parse_from_stdin() {
|
cannam@150
|
27 string buf;
|
cannam@150
|
28 string line;
|
cannam@150
|
29 while (std::getline(std::cin, line)) {
|
cannam@150
|
30 buf += line + "\n";
|
cannam@150
|
31 }
|
cannam@150
|
32
|
cannam@150
|
33 string err;
|
cannam@150
|
34 auto json = Json::parse(buf, err);
|
cannam@150
|
35 if (!err.empty()) {
|
cannam@150
|
36 printf("Failed: %s\n", err.c_str());
|
cannam@150
|
37 } else {
|
cannam@150
|
38 printf("Result: %s\n", json.dump().c_str());
|
cannam@150
|
39 }
|
cannam@150
|
40 }
|
cannam@150
|
41
|
cannam@150
|
42 int main(int argc, char **argv) {
|
cannam@150
|
43 if (argc == 2 && argv[1] == string("--stdin")) {
|
cannam@150
|
44 parse_from_stdin();
|
cannam@150
|
45 return 0;
|
cannam@150
|
46 }
|
cannam@150
|
47
|
cannam@150
|
48 const string simple_test =
|
cannam@150
|
49 R"({"k1":"v1", "k2":42, "k3":["a",123,true,false,null]})";
|
cannam@150
|
50
|
cannam@150
|
51 string err;
|
cannam@150
|
52 auto json = Json::parse(simple_test, err);
|
cannam@150
|
53
|
cannam@150
|
54 std::cout << "k1: " << json["k1"].string_value() << "\n";
|
cannam@150
|
55 std::cout << "k3: " << json["k3"].dump() << "\n";
|
cannam@150
|
56
|
cannam@150
|
57 for (auto &k : json["k3"].array_items()) {
|
cannam@150
|
58 std::cout << " - " << k.dump() << "\n";
|
cannam@150
|
59 }
|
cannam@150
|
60
|
cannam@150
|
61 const string comment_test = R"({
|
cannam@150
|
62 // comment /* with nested comment */
|
cannam@150
|
63 "a": 1,
|
cannam@150
|
64 // comment
|
cannam@150
|
65 // continued
|
cannam@150
|
66 "b": "text",
|
cannam@150
|
67 /* multi
|
cannam@150
|
68 line
|
cannam@150
|
69 comment */
|
cannam@150
|
70 // and single-line comment
|
cannam@150
|
71 "c": [1, 2, 3]
|
cannam@150
|
72 })";
|
cannam@150
|
73
|
cannam@150
|
74 string err_comment;
|
cannam@150
|
75 auto json_comment = Json::parse(
|
cannam@150
|
76 comment_test, err_comment, JsonParse::COMMENTS);
|
cannam@150
|
77 if (!err_comment.empty()) {
|
cannam@150
|
78 printf("Failed: %s\n", err_comment.c_str());
|
cannam@150
|
79 } else {
|
cannam@150
|
80 printf("Result: %s\n", json_comment.dump().c_str());
|
cannam@150
|
81 }
|
cannam@150
|
82
|
cannam@150
|
83 string failing_comment_test = R"({
|
cannam@150
|
84 /* bad comment
|
cannam@150
|
85 "a": 1,
|
cannam@150
|
86 })";
|
cannam@150
|
87
|
cannam@150
|
88 string err_failing_comment;
|
cannam@150
|
89 auto json_failing_comment = Json::parse(
|
cannam@150
|
90 failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
|
cannam@150
|
91 if (!err_failing_comment.empty()) {
|
cannam@150
|
92 printf("Failed: %s\n", err_failing_comment.c_str());
|
cannam@150
|
93 } else {
|
cannam@150
|
94 printf("Result: %s\n", json_failing_comment.dump().c_str());
|
cannam@150
|
95 }
|
cannam@150
|
96
|
cannam@150
|
97 failing_comment_test = R"({
|
cannam@150
|
98 / / bad comment })";
|
cannam@150
|
99
|
cannam@150
|
100 json_failing_comment = Json::parse(
|
cannam@150
|
101 failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
|
cannam@150
|
102 if (!err_failing_comment.empty()) {
|
cannam@150
|
103 printf("Failed: %s\n", err_failing_comment.c_str());
|
cannam@150
|
104 } else {
|
cannam@150
|
105 printf("Result: %s\n", json_failing_comment.dump().c_str());
|
cannam@150
|
106 }
|
cannam@150
|
107
|
cannam@150
|
108 failing_comment_test = R"({// bad comment })";
|
cannam@150
|
109
|
cannam@150
|
110 json_failing_comment = Json::parse(
|
cannam@150
|
111 failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
|
cannam@150
|
112 if (!err_failing_comment.empty()) {
|
cannam@150
|
113 printf("Failed: %s\n", err_failing_comment.c_str());
|
cannam@150
|
114 } else {
|
cannam@150
|
115 printf("Result: %s\n", json_failing_comment.dump().c_str());
|
cannam@150
|
116 }
|
cannam@150
|
117
|
cannam@150
|
118 failing_comment_test = R"({
|
cannam@150
|
119 "a": 1
|
cannam@150
|
120 }/)";
|
cannam@150
|
121
|
cannam@150
|
122 json_failing_comment = Json::parse(
|
cannam@150
|
123 failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
|
cannam@150
|
124 if (!err_failing_comment.empty()) {
|
cannam@150
|
125 printf("Failed: %s\n", err_failing_comment.c_str());
|
cannam@150
|
126 } else {
|
cannam@150
|
127 printf("Result: %s\n", json_failing_comment.dump().c_str());
|
cannam@150
|
128 }
|
cannam@150
|
129
|
cannam@150
|
130 failing_comment_test = R"({/* bad
|
cannam@150
|
131 comment *})";
|
cannam@150
|
132
|
cannam@150
|
133 json_failing_comment = Json::parse(
|
cannam@150
|
134 failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
|
cannam@150
|
135 if (!err_failing_comment.empty()) {
|
cannam@150
|
136 printf("Failed: %s\n", err_failing_comment.c_str());
|
cannam@150
|
137 } else {
|
cannam@150
|
138 printf("Result: %s\n", json_failing_comment.dump().c_str());
|
cannam@150
|
139 }
|
cannam@150
|
140
|
cannam@150
|
141 std::list<int> l1 { 1, 2, 3 };
|
cannam@150
|
142 std::vector<int> l2 { 1, 2, 3 };
|
cannam@150
|
143 std::set<int> l3 { 1, 2, 3 };
|
cannam@150
|
144 assert(Json(l1) == Json(l2));
|
cannam@150
|
145 assert(Json(l2) == Json(l3));
|
cannam@150
|
146
|
cannam@150
|
147 std::map<string, string> m1 { { "k1", "v1" }, { "k2", "v2" } };
|
cannam@150
|
148 std::unordered_map<string, string> m2 { { "k1", "v1" }, { "k2", "v2" } };
|
cannam@150
|
149 assert(Json(m1) == Json(m2));
|
cannam@150
|
150
|
cannam@150
|
151 // Json literals
|
cannam@150
|
152 Json obj = Json::object({
|
cannam@150
|
153 { "k1", "v1" },
|
cannam@150
|
154 { "k2", 42.0 },
|
cannam@150
|
155 { "k3", Json::array({ "a", 123.0, true, false, nullptr }) },
|
cannam@150
|
156 });
|
cannam@150
|
157
|
cannam@150
|
158 std::cout << "obj: " << obj.dump() << "\n";
|
cannam@150
|
159
|
cannam@150
|
160 assert(Json("a").number_value() == 0);
|
cannam@150
|
161 assert(Json("a").string_value() == "a");
|
cannam@150
|
162 assert(Json().number_value() == 0);
|
cannam@150
|
163
|
cannam@150
|
164 assert(obj == json);
|
cannam@150
|
165 assert(Json(42) == Json(42.0));
|
cannam@150
|
166 assert(Json(42) != Json(42.1));
|
cannam@150
|
167
|
cannam@150
|
168 const string unicode_escape_test =
|
cannam@150
|
169 R"([ "blah\ud83d\udca9blah\ud83dblah\udca9blah\u0000blah\u1234" ])";
|
cannam@150
|
170
|
cannam@150
|
171 const char utf8[] = "blah" "\xf0\x9f\x92\xa9" "blah" "\xed\xa0\xbd" "blah"
|
cannam@150
|
172 "\xed\xb2\xa9" "blah" "\0" "blah" "\xe1\x88\xb4";
|
cannam@150
|
173
|
cannam@150
|
174 Json uni = Json::parse(unicode_escape_test, err);
|
cannam@150
|
175 assert(uni[0].string_value().size() == (sizeof utf8) - 1);
|
cannam@150
|
176 assert(std::memcmp(uni[0].string_value().data(), utf8, sizeof utf8) == 0);
|
cannam@150
|
177
|
cannam@150
|
178 // Demonstrates the behavior change in Xcode 7 / Clang 3.7 described
|
cannam@150
|
179 // here: https://llvm.org/bugs/show_bug.cgi?id=23812
|
cannam@150
|
180 Json nested_array = Json::array { Json::array { 1, 2, 3 } };
|
cannam@150
|
181 assert(nested_array.is_array());
|
cannam@150
|
182 assert(nested_array.array_items().size() == 1);
|
cannam@150
|
183 assert(nested_array.array_items()[0].is_array());
|
cannam@150
|
184 assert(nested_array.array_items()[0].array_items().size() == 3);
|
cannam@150
|
185
|
cannam@150
|
186 Json my_json = Json::object {
|
cannam@150
|
187 { "key1", "value1" },
|
cannam@150
|
188 { "key2", false },
|
cannam@150
|
189 { "key3", Json::array { 1, 2, 3 } },
|
cannam@150
|
190 };
|
cannam@150
|
191 std::string json_str = my_json.dump();
|
cannam@150
|
192 printf("%s\n", json_str.c_str());
|
cannam@150
|
193
|
cannam@150
|
194 class Point {
|
cannam@150
|
195 public:
|
cannam@150
|
196 int x;
|
cannam@150
|
197 int y;
|
cannam@150
|
198 Point (int x, int y) : x(x), y(y) {}
|
cannam@150
|
199 Json to_json() const { return Json::array { x, y }; }
|
cannam@150
|
200 };
|
cannam@150
|
201
|
cannam@150
|
202 std::vector<Point> points = { { 1, 2 }, { 10, 20 }, { 100, 200 } };
|
cannam@150
|
203 std::string points_json = Json(points).dump();
|
cannam@150
|
204 printf("%s\n", points_json.c_str());
|
cannam@150
|
205 }
|