json_data.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. * Copyright (C) 2021 Duowan Inc. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing,
  11. * software distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef __X_PACK_JSON_DATA_H
  17. #define __X_PACK_JSON_DATA_H
  18. /*
  19. It is more reasonable to rely on JsonData for encoder and decoder,
  20. but in order to implement decode and String in JsonData for easy use,
  21. so the other way around
  22. */
  23. #include "json_encoder.h"
  24. #include "json_decoder.h"
  25. namespace xpack {
  26. // wrapper for rapidjson::Value.
  27. // If we use other json parser someday, users won’t have to modify the code.
  28. // Most of the code is copied from rapidjson.
  29. enum JsonType {
  30. kNullType = 0, //!< null
  31. kFalseType = 1, //!< false
  32. kTrueType = 2, //!< true
  33. kObjectType = 3, //!< object
  34. kArrayType = 4, //!< array
  35. kStringType = 5, //!< string
  36. kNumberType = 6 //!< number
  37. };
  38. class JsonEncoder;
  39. // Currently JsonData is read-only and may support modification in the future
  40. class JsonData:private noncopyable {
  41. class MemberIterator {
  42. public:
  43. MemberIterator(rapidjson::Value::ConstMemberIterator iter, JsonData* parent):_iter(iter),_parent(parent){}
  44. bool operator != (const MemberIterator &that) const {
  45. return _iter != that._iter;
  46. }
  47. MemberIterator& operator ++ () {
  48. ++_iter;
  49. return *this;
  50. }
  51. const char *Key() const {
  52. return _iter->name.GetString();
  53. }
  54. JsonData& Val() const {
  55. return _parent->member(&(_iter->value), *(_parent->alloc()));
  56. }
  57. private:
  58. rapidjson::Value::ConstMemberIterator _iter;
  59. JsonData* _parent;
  60. };
  61. public:
  62. typedef MemberIterator Iterator;
  63. // check type
  64. JsonType Type() const {
  65. if (_val == NULL) {
  66. return kNullType;
  67. }
  68. return static_cast<JsonType>(_val->GetType());
  69. }
  70. bool IsNull() const { return _val->IsNull(); }
  71. bool IsBool() const { return _val->IsBool(); }
  72. bool IsObject() const { return _val->IsObject(); }
  73. bool IsArray() const { return _val->IsArray(); }
  74. bool IsNumber() const { return _val->IsNumber(); }
  75. bool IsDouble() const { return _val->IsDouble(); }
  76. bool IsString() const { return _val->IsString(); }
  77. std::string GetString() const {return _val->GetString(); }
  78. bool GetBool() const {return _val->GetBool();}
  79. int GetInt() const {return _val->GetInt();}
  80. unsigned int GetUint() const {return _val->GetUint();}
  81. int64_t GetInt64() const {return _val->GetInt64();}
  82. uint64_t GetUint64() const {return _val->GetUint64();}
  83. float GetFloat() const {return _val->GetFloat();}
  84. double GetDouble() const {return _val->GetDouble();}
  85. // check is valid JsonData
  86. operator bool() const {
  87. return NULL != _val;
  88. }
  89. // get array size
  90. size_t Size() const {
  91. if (_val->IsArray()) {
  92. return (size_t)_val->Size();
  93. } else {
  94. return 0;
  95. }
  96. }
  97. JsonData& operator[](size_t index) {
  98. JsonData *d = alloc();
  99. if (NULL != _val && _val->IsArray()) {
  100. if (index < (size_t)_val->Size()) {
  101. d->_val = &(*_val)[(rapidjson::SizeType)index];
  102. } else {
  103. // TODO decode_exception("Out of index", NULL);
  104. }
  105. } else {
  106. // TODO decode_exception("not array", NULL);
  107. }
  108. return *d;
  109. }
  110. JsonData& operator[](const char*key) {
  111. JsonData *d = alloc();
  112. if (NULL != _val && _val->IsObject()) {
  113. rapidjson::Value::ConstMemberIterator iter;
  114. if (_val->MemberEnd() != (iter=_val->FindMember(key))) {
  115. d->_val = &(iter->value);
  116. }
  117. } else {
  118. // TODO decode_exception("not object", key);
  119. }
  120. return *d;
  121. }
  122. // iter
  123. Iterator Begin() {
  124. return Iterator(_val->MemberBegin(), this);
  125. }
  126. Iterator End() {
  127. return Iterator(_val->MemberEnd(), this);
  128. }
  129. // JsonData is noncopyable, if need to pass it outside the function, use Swap
  130. // DO NOT Swap child node. JsonData[0].Swap will crash
  131. // If the compiler supports C++11, you should use shared_ptr<JsonData> instead of Swap
  132. void Swap(JsonData& d) {
  133. rapidjson::MemoryPoolAllocator<> *allocator = _allocator;
  134. const rapidjson::Value *val = _val;
  135. bool alloc = _alloc;
  136. std::string raw_data = _raw_data;
  137. _allocator = d._allocator;
  138. _val = d._val;
  139. _alloc = d._alloc;
  140. _raw_data = d._raw_data;
  141. d._allocator = allocator;
  142. d._val = val;
  143. d._alloc = alloc;
  144. d._raw_data = raw_data;
  145. }
  146. template <class T>
  147. bool decode(T &val) const {
  148. JsonDecoder d(_val);
  149. return d.decode(NULL, val, NULL);
  150. }
  151. std::string String() {
  152. if (_raw_data.empty()) {
  153. JsonEncoder e(-1);
  154. xpack_encode(e, NULL, NULL);
  155. _raw_data = e.String();
  156. }
  157. return _raw_data;
  158. }
  159. public:
  160. //friend class JsonDecoder;
  161. JsonData():_allocator(NULL),_val(NULL), _alloc(false) {
  162. }
  163. ~JsonData() {
  164. reset();
  165. if (NULL != _allocator) {
  166. delete _allocator;
  167. _allocator = NULL;
  168. }
  169. }
  170. bool xpack_decode(JsonDecoder &obj, const char*key, const Extend *ext) {
  171. const rapidjson::Value *v = obj.get_val(key);
  172. if (NULL == v) {
  173. if (NULL!=key && Extend::Mandatory(ext)) {
  174. obj.decode_exception("mandatory key not found", key);
  175. }
  176. return false;
  177. } else {
  178. copy(v);
  179. return true;
  180. }
  181. }
  182. bool xpack_encode(JsonEncoder &obj, const char*key, const Extend *ext) const {
  183. switch (Type()){
  184. case kNullType:
  185. return false; // not support write null now
  186. case kFalseType:
  187. case kTrueType:
  188. return obj.encode(key, GetBool(), ext);
  189. case kStringType:
  190. return obj.encode(key, GetString(), ext);
  191. case kNumberType:
  192. if (IsDouble()) {
  193. return obj.encode(key, GetDouble(), ext);
  194. } else {
  195. return obj.encode(key, GetInt64(), ext);
  196. }
  197. case kObjectType:
  198. obj.ObjectBegin(key, ext);
  199. for (rapidjson::Value::ConstMemberIterator iter = _val->MemberBegin(); iter!=_val->MemberEnd(); ++iter){
  200. JsonData d;
  201. d._val = &iter->value;
  202. d.xpack_encode(obj, iter->name.GetString(), ext);
  203. }
  204. obj.ObjectEnd(key, ext);
  205. break;
  206. case kArrayType:{
  207. obj.ArrayBegin(key, ext);
  208. size_t max = Size();
  209. for (size_t i = 0; i<max; ++i) {
  210. JsonData d;
  211. d._val = &(*_val)[(rapidjson::SizeType)i];
  212. d.xpack_encode(obj, NULL, ext);
  213. }
  214. obj.ArrayEnd(key, ext);
  215. }
  216. break;
  217. }
  218. return true;
  219. }
  220. private:
  221. JsonData(const rapidjson::Value *v):_allocator(NULL), _val(v), _alloc(false) {
  222. }
  223. JsonData* alloc() {
  224. JsonData *d = new JsonData();
  225. _collector.push_back(d);
  226. return d;
  227. }
  228. // after xpack::json::decode, JsonDecoder will destruct, so we need copy data
  229. // to JsonData, and copy can only be called by decode
  230. void copy(const rapidjson::Value *v) {
  231. if (NULL == _allocator) {
  232. _allocator = new rapidjson::MemoryPoolAllocator<>();
  233. }
  234. reset();
  235. _val = new rapidjson::Value(*v, *_allocator, true);
  236. _alloc = true;
  237. }
  238. void reset() {
  239. if (_alloc && _val!=NULL) {
  240. delete _val;
  241. _val = NULL;
  242. _alloc = false;
  243. }
  244. for (size_t i=0; i<_collector.size(); ++i) {
  245. delete _collector[i];
  246. }
  247. _collector.clear();
  248. }
  249. JsonData& member(const rapidjson::Value *v, JsonData&d) const {
  250. d._val = v;
  251. return d;
  252. }
  253. rapidjson::MemoryPoolAllocator<> *_allocator;
  254. const rapidjson::Value *_val;
  255. bool _alloc;
  256. std::vector<JsonData*> _collector;
  257. std::string _raw_data;
  258. };
  259. template<>
  260. struct is_xpack_xtype<JsonData> {static bool const value = true;};
  261. inline bool xpack_xtype_decode(JsonDecoder &obj, const char*key, JsonData &val, const Extend *ext) {
  262. return val.xpack_decode(obj, key, ext);
  263. }
  264. inline bool xpack_xtype_encode(JsonEncoder &obj, const char*key, const JsonData &val, const Extend *ext) {
  265. return val.xpack_encode(obj, key, ext);
  266. }
  267. }
  268. #endif