json.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. #pragma once
  2. #include <nlohmann/json.hpp>
  3. #include <string>
  4. #include <vector>
  5. #include <type_traits>
  6. #include "base/define.h"
  7. #include "base/exception.h"
  8. namespace ylib
  9. {
  10. /**
  11. * @brief JSON 封装(基于 nlohmann/json)
  12. * 保留历史常用 API:from / to_string / to<T> / keys / exist / is_* / type 赋值
  13. * private 继承:隐藏基类隐式 operator ValueType(),保证 if (j["key"]) 走 truthy()
  14. * 无额外数据成员;需要底层 API 时用 raw()
  15. */
  16. class json : private nlohmann::json
  17. {
  18. public:
  19. using base = nlohmann::json;
  20. // 常用底层能力(不导出 begin/end,避免被当成 range 构造成 nlohmann 数组)
  21. using base::dump;
  22. using base::contains;
  23. using base::find;
  24. using base::at;
  25. using base::get;
  26. using base::get_ref;
  27. using base::get_ptr;
  28. enum type
  29. {
  30. null,
  31. obj,
  32. empty,
  33. array,
  34. boolean,
  35. number,
  36. string
  37. };
  38. json() : base(nullptr) {}
  39. json(const json& other) = default;
  40. json(json&& other) noexcept = default;
  41. json(const base& other) : base(other) {}
  42. json(base&& other) noexcept : base(std::move(other)) {}
  43. json(std::nullptr_t) : base(nullptr) {}
  44. /// 按 type 枚举构造(避免 json x = type::array 退化成整数)
  45. json(type t) : base(nullptr) { *this = t; }
  46. json(const std::string& value) : base(value) {}
  47. json(const char* value) : base(value ? value : "") {}
  48. json(bool value) : base(value) {}
  49. json(int32 value) : base(value) {}
  50. json(uint32 value) : base(value) {}
  51. json(int64 value) : base(value) {}
  52. json(uint64 value) : base(value) {}
  53. json(double value) : base(value) {}
  54. json(float value) : base(value) {}
  55. json& operator=(const json& other) = default;
  56. json& operator=(json&& other) noexcept = default;
  57. json& operator=(const base& other)
  58. {
  59. base::operator=(other);
  60. return *this;
  61. }
  62. json& operator=(base&& other) noexcept
  63. {
  64. base::operator=(std::move(other));
  65. return *this;
  66. }
  67. json& operator=(std::nullptr_t)
  68. {
  69. base::operator=(nullptr);
  70. return *this;
  71. }
  72. json& operator=(const std::string& value)
  73. {
  74. base::operator=(value);
  75. return *this;
  76. }
  77. json& operator=(const char* value)
  78. {
  79. if (value == nullptr)
  80. base::operator=(nullptr);
  81. else
  82. base::operator=(value);
  83. return *this;
  84. }
  85. json& operator=(bool value)
  86. {
  87. base::operator=(value);
  88. return *this;
  89. }
  90. json& operator=(int32 value)
  91. {
  92. base::operator=(value);
  93. return *this;
  94. }
  95. json& operator=(uint32 value)
  96. {
  97. base::operator=(value);
  98. return *this;
  99. }
  100. json& operator=(int64 value)
  101. {
  102. base::operator=(value);
  103. return *this;
  104. }
  105. json& operator=(uint64 value)
  106. {
  107. base::operator=(value);
  108. return *this;
  109. }
  110. json& operator=(double value)
  111. {
  112. base::operator=(value);
  113. return *this;
  114. }
  115. json& operator=(float value)
  116. {
  117. base::operator=(value);
  118. return *this;
  119. }
  120. json& operator=(type t)
  121. {
  122. switch (t)
  123. {
  124. case type::null:
  125. case type::empty:
  126. base::operator=(nullptr);
  127. break;
  128. case type::obj:
  129. base::operator=(base::object());
  130. break;
  131. case type::array:
  132. base::operator=(base::array());
  133. break;
  134. case type::boolean:
  135. base::operator=(false);
  136. break;
  137. case type::number:
  138. base::operator=(0);
  139. break;
  140. case type::string:
  141. base::operator=("");
  142. break;
  143. }
  144. return *this;
  145. }
  146. /// 显式拿到底层 nlohmann::json(private 继承后不可隐式转换)
  147. base& raw() noexcept { return *this; }
  148. const base& raw() const noexcept { return *this; }
  149. static json from(const std::string& value)
  150. {
  151. if (value.empty())
  152. return json();
  153. try
  154. {
  155. // cb=nullptr, allow_exceptions=true, ignore_comments=true(支持 // 与 /* */)
  156. return json(base::parse(value, nullptr, true, true));
  157. }
  158. catch (...)
  159. {
  160. return json();
  161. }
  162. }
  163. bool parse(const std::string& value)
  164. {
  165. try
  166. {
  167. // cb=nullptr, allow_exceptions=true, ignore_comments=true(支持 // 与 /* */)
  168. *this = base::parse(value, nullptr, true, true);
  169. return true;
  170. }
  171. catch (...)
  172. {
  173. base::operator=(nullptr);
  174. return false;
  175. }
  176. }
  177. // 兼容旧签名;path / safe 已废弃为空操作
  178. void path(const std::string&) {}
  179. void safe(bool) {}
  180. bool safe() { return false; }
  181. std::string to_string(bool format = false) const
  182. {
  183. return dump(format ? 2 : -1);
  184. }
  185. uint32 size() const { return static_cast<uint32>(base::size()); }
  186. void resize(uint32 n)
  187. {
  188. if (!base::is_array())
  189. *this = base::array();
  190. base::get_ref<base::array_t&>().resize(n);
  191. }
  192. // null / 空对象 / 空数组 / 空字符串 视为 empty(比旧实现语义更清晰)
  193. bool is_empty() const { return base::empty(); }
  194. bool is_null() const { return base::is_null(); }
  195. bool is_obj() const { return base::is_object(); }
  196. bool is_array() const { return base::is_array(); }
  197. bool is_bool() const { return base::is_boolean(); }
  198. bool is_number() const { return base::is_number(); }
  199. bool is_string() const { return base::is_string(); }
  200. /**
  201. * @brief 真值:null / "" / 空数组 / 空对象 → false;其余(含 0、false)为 true
  202. */
  203. bool truthy() const
  204. {
  205. if (is_null())
  206. return false;
  207. if (is_string())
  208. return !get_ref<const base::string_t&>().empty();
  209. if (is_array() || is_object())
  210. return !base::empty();
  211. return true;
  212. }
  213. /**
  214. * @brief 支持 if (j["key"]);private 继承后不会再落到基类 get<bool>()
  215. */
  216. explicit operator bool() const { return truthy(); }
  217. bool exist(const std::string& name) const { return contains(name); }
  218. void erase(const std::string& key) { base::erase(key); }
  219. void erase(uint32 index)
  220. {
  221. if (is_array() && index < base::size())
  222. base::erase(begin() + static_cast<difference_type>(index));
  223. }
  224. void clear() { base::clear(); }
  225. std::vector<std::string> keys() const
  226. {
  227. std::vector<std::string> result;
  228. if (!is_object())
  229. return result;
  230. result.reserve(base::size());
  231. for (auto it = cbegin(); it != cend(); ++it)
  232. result.push_back(it.key());
  233. return result;
  234. }
  235. json& operator[](const std::string& name)
  236. {
  237. return static_cast<json&>(base::operator[](name));
  238. }
  239. const json& operator[](const std::string& name) const
  240. {
  241. auto it = find(name);
  242. if (it == cend())
  243. {
  244. static const json null_json;
  245. return null_json;
  246. }
  247. return static_cast<const json&>(*it);
  248. }
  249. // const char* 重载:配合 operator bool,避免 body["key"] 与内建下标歧义
  250. json& operator[](const char* name) { return (*this)[std::string(name ? name : "")]; }
  251. const json& operator[](const char* name) const
  252. {
  253. return (*this)[std::string(name ? name : "")];
  254. }
  255. json& operator[](size_t idx)
  256. {
  257. return static_cast<json&>(base::operator[](idx));
  258. }
  259. const json& operator[](size_t idx) const
  260. {
  261. return static_cast<const json&>(base::at(idx));
  262. }
  263. json& operator[](int idx)
  264. {
  265. return static_cast<json&>(base::operator[](idx));
  266. }
  267. const json& operator[](int idx) const
  268. {
  269. return static_cast<const json&>(base::at(idx));
  270. }
  271. json& operator[](unsigned int idx)
  272. {
  273. return static_cast<json&>(base::operator[](idx));
  274. }
  275. const json& operator[](unsigned int idx) const
  276. {
  277. return static_cast<const json&>(base::at(idx));
  278. }
  279. using base::push_back;
  280. void push_back(const json& value)
  281. {
  282. base::push_back(static_cast<const base&>(value));
  283. }
  284. // 字面量重载:避免与基类 push_back(basic_json) 因隐式转换产生歧义
  285. void push_back(bool value) { base::push_back(value); }
  286. void push_back(int32 value) { base::push_back(value); }
  287. void push_back(uint32 value) { base::push_back(value); }
  288. void push_back(int64 value) { base::push_back(value); }
  289. void push_back(uint64 value) { base::push_back(value); }
  290. void push_back(double value) { base::push_back(value); }
  291. void push_back(float value) { base::push_back(value); }
  292. void push_back(const char* value) { base::push_back(value ? value : ""); }
  293. void push_back(const std::string& value) { base::push_back(value); }
  294. bool operator==(const json& rhs) const
  295. {
  296. return static_cast<const base&>(*this) == static_cast<const base&>(rhs);
  297. }
  298. bool operator!=(const json& rhs) const { return !(*this == rhs); }
  299. template<typename T_TO>
  300. T_TO to(bool /*check*/ = false) const
  301. {
  302. using T = T_TO;
  303. if constexpr (std::is_same_v<T, std::string>)
  304. {
  305. if (is_string())
  306. return get<std::string>();
  307. if (is_null())
  308. return std::string();
  309. if (is_boolean())
  310. return get<bool>() ? "true" : "false";
  311. if (is_number_unsigned())
  312. return std::to_string(get<uint64_t>());
  313. if (is_number_integer())
  314. return std::to_string(get<int64_t>());
  315. if (is_number_float())
  316. return std::to_string(get<double>());
  317. return dump();
  318. }
  319. else if constexpr (std::is_same_v<T, bool>)
  320. {
  321. if (is_boolean())
  322. return get<bool>();
  323. if (is_number())
  324. return get<double>() != 0.0;
  325. if (is_string())
  326. {
  327. const auto& s = get_ref<const base::string_t&>();
  328. return s == "1" || s == "true" || s == "TRUE" || s == "True";
  329. }
  330. return false;
  331. }
  332. else if constexpr (std::is_arithmetic_v<T>)
  333. {
  334. if (is_number())
  335. return get<T>();
  336. if (is_boolean())
  337. return static_cast<T>(get<bool>() ? 1 : 0);
  338. if (is_string())
  339. {
  340. try
  341. {
  342. const auto& s = get_ref<const base::string_t&>();
  343. if constexpr (std::is_floating_point_v<T>)
  344. return static_cast<T>(std::stod(s));
  345. else if constexpr (std::is_signed_v<T>)
  346. return static_cast<T>(std::stoll(s));
  347. else
  348. return static_cast<T>(std::stoull(s));
  349. }
  350. catch (...)
  351. {
  352. return T{};
  353. }
  354. }
  355. return T{};
  356. }
  357. else if constexpr (std::is_same_v<T, std::vector<std::string>>)
  358. {
  359. std::vector<std::string> result;
  360. if (!is_array())
  361. return result;
  362. for (const auto& el : *this)
  363. result.push_back(static_cast<const json&>(el).template to<std::string>());
  364. return result;
  365. }
  366. else if constexpr (std::is_same_v<T, std::vector<json>>)
  367. {
  368. std::vector<json> result;
  369. if (!is_array())
  370. return result;
  371. for (const auto& el : *this)
  372. result.push_back(static_cast<const json&>(el));
  373. return result;
  374. }
  375. else
  376. {
  377. throw ylib::exception("json::to unsupported type");
  378. }
  379. }
  380. };
  381. }