json.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //
  2. // json.cpp
  3. // json
  4. //
  5. // Created by Sam Jaffe on 1/30/16.
  6. // Copyright © 2016 Sam Jaffe. All rights reserved.
  7. //
  8. #include "json.h"
  9. #include "json_parser.hpp"
  10. #include "json_binder.hpp"
  11. struct test_t {
  12. int a, b;
  13. };
  14. struct test_2_t {
  15. test_t t;
  16. double d;
  17. };
  18. int main(int argc, char const** argv) {
  19. auto bind1 = json::binder::object_binder<test_t>{}
  20. ("a", &test_t::a)
  21. ("b", &test_t::b);
  22. json::binder::tuple_binder<test_t>{}
  23. (&test_t::a)
  24. (&test_t::b);
  25. auto bind2 = json::binder::object_binder<test_2_t>{}
  26. ("t", &test_2_t::t, bind1)("d", &test_2_t::d);
  27. {
  28. test_t out;
  29. std::string data = "{\"a\":1,\"b\":2}";
  30. json::parser::parse(json::binder::bind(out, bind1), data);
  31. std::cout << out.a << ',' << out.b << std::endl;
  32. }
  33. {
  34. test_2_t out;
  35. std::string data = "{\"t\":{\"a\":1,\"b\":2},\"d\":1.5}";
  36. json::parser::parse(json::binder::bind(out, bind2), data);
  37. std::cout << '{' << out.t.a << ',' << out.t.b << "}," << out.d << std::endl;
  38. }
  39. }
  40. const json::value json::value::null_value{};
  41. namespace {
  42. void parse_object(json::value& json, char const*& data);
  43. void parse_array(json::value& json, char const*& data);
  44. void parse_one_token(json::value& json, char const*& data);
  45. void parse_one_token(json::value& json, char const*& data) {
  46. const char ch = json::helper::get_next_element(data);
  47. if (ch == '{') {
  48. parse_object(json, ++data);
  49. } else if (ch == '[') {
  50. parse_array(json, ++data);
  51. } else if (ch == '"') {
  52. json::helper::parse_string(json, ++data);
  53. } else if (isnumber(ch)) {
  54. json::helper::parse_numeric(json, data);
  55. } else if (!strncmp(data, "true", 4)) {
  56. json = true;
  57. } else if (!strncmp(data, "false", 5)) {
  58. json = false;
  59. } else {
  60. throw json::malformed_json_exception(std::string("Expected the start of a JSON element, found character '") + ch + "' instead");
  61. }
  62. }
  63. void parse_object(json::value& json, char const*& data) {
  64. std::string key;
  65. while (*data && *data != '}') {
  66. json::helper::parse_string(key, data);
  67. if (json::helper::get_next_element(data) != ':') {
  68. throw json::malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead");
  69. }
  70. parse_one_token(json[key], ++data);
  71. json::helper::advance_to_boundary<'}'>(data);
  72. }
  73. if (*data) ++data;
  74. else throw json::malformed_json_exception("Reached end of parse string without finding object end");
  75. }
  76. void parse_array(json::value& json, char const*& data) {
  77. size_t current_idx = 0;
  78. while (*data && *data != ']') {
  79. parse_one_token(json[current_idx++], data);
  80. json::helper::advance_to_boundary<']'>(data);
  81. }
  82. if (*data) ++data;
  83. else throw json::malformed_json_exception("Reached end of parse string without finding array end");
  84. }
  85. }
  86. namespace json {
  87. namespace parser {
  88. void parse(json::value& json, char const* data) {
  89. parse_one_token(json, data);
  90. if (*data) throw json::malformed_json_exception("Expected a single json token in top-level parse");
  91. }
  92. }
  93. }
  94. void json::value::parse(char const* data) { parser::parse(*this, data); }
  95. void json::value::parse(std::string const& str) { parser::parse(*this, str); }
  96. void json::value::parse(std::istream & in) { parser::parse(*this, in); }
  97. json::value& json::value::operator[](const size_t idx) {
  98. if (!is_array()) {
  99. data.set<array_jt>();
  100. }
  101. array_jt & val = data.get<array_jt>();
  102. if (val.size() <= idx) val.resize(idx+1);
  103. return val[idx];
  104. }
  105. json::value const& json::value::operator[](const size_t idx) const {
  106. if (!is_array()) return null_value;
  107. array_jt const& val = data.get<array_jt>();
  108. if (val.size() <= idx) return null_value;
  109. else return val[idx];
  110. }
  111. json::value& json::value::operator[](std::string const& key) {
  112. if (!is_object()) {
  113. data.set<object_jt>();
  114. }
  115. return data.get<object_jt>()[key];
  116. }
  117. json::value const& json::value::operator[](std::string const& key) const {
  118. if (!is_object()) return null_value;
  119. object_jt const& val = data.get<object_jt>();
  120. auto it = val.find(key);
  121. if (it != val.end()) {
  122. return it->second;
  123. } else {
  124. return null_value;
  125. }
  126. }
  127. json::value::string_jt const& json::value::as_string() const {
  128. return data.get<string_jt>();
  129. }
  130. json::value::double_jt json::value::as_double() const {
  131. if (data.is<double_jt>()) {
  132. return data.get<double_jt>();
  133. } else if (data.is<int_jt>()) {
  134. return static_cast<double_jt>(data.get<int_jt>());
  135. } else if (data.is<bool_jt>()) {
  136. return data.get<bool_jt>() ? 1.0 : 0.0;
  137. } else {
  138. return 0.0;
  139. }
  140. }
  141. json::value::int_jt json::value::as_int() const {
  142. if (data.is<double_jt>()) {
  143. return static_cast<int_jt>(data.get<double_jt>());
  144. } else if (data.is<int_jt>()) {
  145. return data.get<int_jt>();
  146. } else if (data.is<bool_jt>()) {
  147. return data.get<bool_jt>() ? 1 : 0;
  148. } else {
  149. return 0;
  150. }
  151. }
  152. json::value::bool_jt json::value::as_bool() const {
  153. if (data.is<double_jt>()) {
  154. return data.get<double_jt>() != 0;
  155. } else if (data.is<int_jt>()) {
  156. return data.get<int_jt>() != 0;
  157. } else if (data.is<bool_jt>()) {
  158. return data.get<bool_jt>();
  159. } else {
  160. return false;
  161. }
  162. }