JsonNode.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * JsonNode.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. #include "../filesystem/ResourcePath.h"
  12. VCMI_LIB_NAMESPACE_BEGIN
  13. class JsonNode;
  14. using JsonMap = std::map<std::string, JsonNode>;
  15. using JsonVector = std::vector<JsonNode>;
  16. struct Bonus;
  17. class CSelector;
  18. class CAddInfo;
  19. class ILimiter;
  20. class DLL_LINKAGE JsonNode
  21. {
  22. public:
  23. enum class JsonType
  24. {
  25. DATA_NULL,
  26. DATA_BOOL,
  27. DATA_FLOAT,
  28. DATA_STRING,
  29. DATA_VECTOR,
  30. DATA_STRUCT,
  31. DATA_INTEGER
  32. };
  33. private:
  34. using JsonData = std::variant<std::monostate, bool, double, std::string, JsonVector, JsonMap, si64>;
  35. JsonData data;
  36. public:
  37. /// free to use metadata fields
  38. std::string meta;
  39. // meta-flags like override
  40. std::vector<std::string> flags;
  41. //Create empty node
  42. JsonNode(JsonType Type = JsonType::DATA_NULL);
  43. //Create tree from Json-formatted input
  44. explicit JsonNode(const char * data, size_t datasize);
  45. explicit JsonNode(const std::byte * data, size_t datasize);
  46. //Create tree from JSON file
  47. explicit JsonNode(const JsonPath & fileURI);
  48. explicit JsonNode(const std::string & modName, const JsonPath & fileURI);
  49. explicit JsonNode(const JsonPath & fileURI, bool & isValidSyntax);
  50. bool operator == (const JsonNode &other) const;
  51. bool operator != (const JsonNode &other) const;
  52. void setMeta(const std::string & metadata, bool recursive = true);
  53. /// Convert node to another type. Converting to nullptr will clear all data
  54. void setType(JsonType Type);
  55. JsonType getType() const;
  56. bool isNull() const;
  57. bool isNumber() const;
  58. bool isString() const;
  59. bool isVector() const;
  60. bool isStruct() const;
  61. /// true if node contains not-null data that cannot be extended via merging
  62. /// used for generating common base node from multiple nodes (e.g. bonuses)
  63. bool containsBaseData() const;
  64. bool isCompact() const;
  65. /// removes all data from node and sets type to null
  66. void clear();
  67. /// returns bool or bool equivalent of string value if 'success' is true, or false otherwise
  68. bool TryBoolFromString(bool & success) const;
  69. /// non-const accessors, node will change type on type mismatch
  70. bool & Bool();
  71. double & Float();
  72. si64 & Integer();
  73. std::string & String();
  74. JsonVector & Vector();
  75. JsonMap & Struct();
  76. /// const accessors, will cause assertion failure on type mismatch
  77. bool Bool() const;
  78. ///float and integer allowed
  79. double Float() const;
  80. ///only integer allowed
  81. si64 Integer() const;
  82. const std::string & String() const;
  83. const JsonVector & Vector() const;
  84. const JsonMap & Struct() const;
  85. /// returns resolved "json pointer" (string in format "/path/to/node")
  86. const JsonNode & resolvePointer(const std::string & jsonPointer) const;
  87. JsonNode & resolvePointer(const std::string & jsonPointer);
  88. /// convert json tree into specified type. Json tree must have same type as Type
  89. /// Valid types: bool, string, any numeric, map and vector
  90. /// example: convertTo< std::map< std::vector<int> > >();
  91. template<typename Type>
  92. Type convertTo() const;
  93. //operator [], for structs only - get child node by name
  94. JsonNode & operator[](const std::string & child);
  95. const JsonNode & operator[](const std::string & child) const;
  96. JsonNode & operator[](size_t child);
  97. const JsonNode & operator[](size_t child) const;
  98. std::string toJson(bool compact = false) const;
  99. std::vector<std::byte> toBytes(bool compact = false) const;
  100. template <typename Handler> void serialize(Handler &h)
  101. {
  102. h & meta;
  103. h & flags;
  104. h & data;
  105. }
  106. };
  107. namespace JsonDetail
  108. {
  109. // conversion helpers for JsonNode::convertTo (partial template function instantiation is illegal in c++)
  110. template <typename T, int arithm>
  111. struct JsonConvImpl;
  112. template <typename T>
  113. struct JsonConvImpl<T, 1>
  114. {
  115. static T convertImpl(const JsonNode & node)
  116. {
  117. return T((int)node.Float());
  118. }
  119. };
  120. template <typename T>
  121. struct JsonConvImpl<T, 0>
  122. {
  123. static T convertImpl(const JsonNode & node)
  124. {
  125. return T(node.Float());
  126. }
  127. };
  128. template<typename Type>
  129. struct JsonConverter
  130. {
  131. static Type convert(const JsonNode & node)
  132. {
  133. ///this should be triggered only for numeric types and enums
  134. static_assert(std::is_arithmetic_v<Type> || std::is_enum_v<Type> || std::is_class_v<Type>, "Unsupported type for JsonNode::convertTo()!");
  135. return JsonConvImpl<Type, std::is_enum_v<Type> || std::is_class_v<Type> >::convertImpl(node);
  136. }
  137. };
  138. template<typename Type>
  139. struct JsonConverter<std::map<std::string, Type> >
  140. {
  141. static std::map<std::string, Type> convert(const JsonNode & node)
  142. {
  143. std::map<std::string, Type> ret;
  144. for (const JsonMap::value_type & entry : node.Struct())
  145. {
  146. ret.insert(entry.first, entry.second.convertTo<Type>());
  147. }
  148. return ret;
  149. }
  150. };
  151. template<typename Type>
  152. struct JsonConverter<std::set<Type> >
  153. {
  154. static std::set<Type> convert(const JsonNode & node)
  155. {
  156. std::set<Type> ret;
  157. for(const JsonVector::value_type & entry : node.Vector())
  158. {
  159. ret.insert(entry.convertTo<Type>());
  160. }
  161. return ret;
  162. }
  163. };
  164. template<typename Type>
  165. struct JsonConverter<std::vector<Type> >
  166. {
  167. static std::vector<Type> convert(const JsonNode & node)
  168. {
  169. std::vector<Type> ret;
  170. for (const JsonVector::value_type & entry: node.Vector())
  171. {
  172. ret.push_back(entry.convertTo<Type>());
  173. }
  174. return ret;
  175. }
  176. };
  177. template<>
  178. struct JsonConverter<std::string>
  179. {
  180. static std::string convert(const JsonNode & node)
  181. {
  182. return node.String();
  183. }
  184. };
  185. template<>
  186. struct JsonConverter<bool>
  187. {
  188. static bool convert(const JsonNode & node)
  189. {
  190. return node.Bool();
  191. }
  192. };
  193. }
  194. template<typename Type>
  195. Type JsonNode::convertTo() const
  196. {
  197. return JsonDetail::JsonConverter<Type>::convert(*this);
  198. }
  199. VCMI_LIB_NAMESPACE_END