JsonNode.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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 DLL_LINKAGE JsonParsingSettings
  17. {
  18. enum class JsonFormatMode
  19. {
  20. JSON, // strict implementation of json format
  21. JSONC, // json format that also allows comments that start from '//'
  22. JSON5 // Partial support of 'json5' format
  23. };
  24. JsonFormatMode mode = JsonFormatMode::JSON5;
  25. /// Maximum depth of elements
  26. uint32_t maxDepth = 30;
  27. /// If set to true, parser will throw on any encountered error
  28. bool strict = false;
  29. };
  30. class DLL_LINKAGE JsonNode
  31. {
  32. public:
  33. enum class JsonType
  34. {
  35. DATA_NULL,
  36. DATA_BOOL,
  37. DATA_FLOAT,
  38. DATA_STRING,
  39. DATA_VECTOR,
  40. DATA_STRUCT,
  41. DATA_INTEGER
  42. };
  43. private:
  44. using JsonData = std::variant<std::monostate, bool, double, std::string, JsonVector, JsonMap, int64_t>;
  45. JsonData data;
  46. /// Mod-origin of this particular field
  47. std::string modScope;
  48. bool overrideFlag = false;
  49. public:
  50. JsonNode() = default;
  51. /// Create single node with specified value
  52. explicit JsonNode(bool boolean);
  53. explicit JsonNode(int32_t number);
  54. explicit JsonNode(uint32_t number);
  55. explicit JsonNode(int64_t number);
  56. explicit JsonNode(double number);
  57. explicit JsonNode(const char * string);
  58. explicit JsonNode(const std::string & string);
  59. /// Create tree from map
  60. explicit JsonNode(const JsonMap & map);
  61. /// Create tree from Json-formatted input
  62. explicit JsonNode(const std::byte * data, size_t datasize, const std::string & fileName);
  63. explicit JsonNode(const std::byte * data, size_t datasize, const JsonParsingSettings & parserSettings, const std::string & fileName);
  64. explicit JsonNode(const char * data, size_t datasize, const std::string & fileName);
  65. explicit JsonNode(const char * data, size_t datasize, const JsonParsingSettings & parserSettings, const std::string & fileName);
  66. /// Create tree from JSON file
  67. explicit JsonNode(const JsonPath & fileURI);
  68. explicit JsonNode(const JsonPath & fileURI, const JsonParsingSettings & parserSettings);
  69. explicit JsonNode(const JsonPath & fileURI, const std::string & modName);
  70. explicit JsonNode(const JsonPath & fileURI, const std::string & modName, bool & isValidSyntax);
  71. bool operator==(const JsonNode & other) const;
  72. bool operator!=(const JsonNode & other) const;
  73. const std::string & getModScope() const;
  74. void setModScope(const std::string & metadata, bool recursive = true);
  75. void setOverrideFlag(bool value);
  76. bool getOverrideFlag() const;
  77. /// Convert node to another type. Converting to nullptr will clear all data
  78. void setType(JsonType Type);
  79. JsonType getType() const;
  80. bool isNull() const;
  81. bool isBool() const;
  82. bool isNumber() const;
  83. bool isString() const;
  84. bool isVector() const;
  85. bool isStruct() const;
  86. /// true if node contains not-null data that cannot be extended via merging
  87. /// used for generating common base node from multiple nodes (e.g. bonuses)
  88. bool containsBaseData() const;
  89. bool isCompact() const;
  90. /// removes all data from node and sets type to null
  91. void clear();
  92. /// non-const accessors, node will change type on type mismatch
  93. bool & Bool();
  94. double & Float();
  95. si64 & Integer();
  96. std::string & String();
  97. JsonVector & Vector();
  98. JsonMap & Struct();
  99. /// const accessors, will cause assertion failure on type mismatch
  100. bool Bool() const;
  101. ///float and integer allowed
  102. double Float() const;
  103. ///only integer allowed
  104. si64 Integer() const;
  105. const std::string & String() const;
  106. const JsonVector & Vector() const;
  107. const JsonMap & Struct() const;
  108. /// returns resolved "json pointer" (string in format "/path/to/node")
  109. const JsonNode & resolvePointer(const std::string & jsonPointer) const;
  110. JsonNode & resolvePointer(const std::string & jsonPointer);
  111. /// convert json tree into specified type. Json tree must have same type as Type
  112. /// Valid types: bool, string, any numeric, map and vector
  113. /// example: convertTo< std::map< std::vector<int> > >();
  114. template<typename Type>
  115. Type convertTo() const;
  116. //operator [], for structs only - get child node by name
  117. JsonNode & operator[](const std::string & child);
  118. const JsonNode & operator[](const std::string & child) const;
  119. JsonNode & operator[](size_t child);
  120. const JsonNode & operator[](size_t child) const;
  121. std::string toCompactString() const;
  122. std::string toString() const;
  123. std::vector<std::byte> toBytes() const;
  124. template<typename Handler>
  125. void serialize(Handler & h)
  126. {
  127. h & modScope;
  128. h & overrideFlag;
  129. h & data;
  130. }
  131. };
  132. namespace JsonDetail
  133. {
  134. inline void convert(bool & value, const JsonNode & node)
  135. {
  136. value = node.Bool();
  137. }
  138. template<typename T>
  139. auto convert(T & value, const JsonNode & node) -> std::enable_if_t<std::is_integral_v<T>>
  140. {
  141. value = node.Integer();
  142. }
  143. template<typename T>
  144. auto convert(T & value, const JsonNode & node) -> std::enable_if_t<std::is_floating_point_v<T>>
  145. {
  146. value = node.Float();
  147. }
  148. inline void convert(std::string & value, const JsonNode & node)
  149. {
  150. value = node.String();
  151. }
  152. template<typename Type>
  153. void convert(std::map<std::string, Type> & value, const JsonNode & node)
  154. {
  155. value.clear();
  156. for(const JsonMap::value_type & entry : node.Struct())
  157. value.emplace(entry.first, entry.second.convertTo<Type>());
  158. }
  159. template<typename Type>
  160. void convert(std::set<Type> & value, const JsonNode & node)
  161. {
  162. value.clear();
  163. for(const JsonVector::value_type & entry : node.Vector())
  164. {
  165. value.insert(entry.convertTo<Type>());
  166. }
  167. }
  168. template<typename Type>
  169. void convert(std::vector<Type> & value, const JsonNode & node)
  170. {
  171. value.clear();
  172. for(const JsonVector::value_type & entry : node.Vector())
  173. {
  174. value.push_back(entry.convertTo<Type>());
  175. }
  176. }
  177. }
  178. template<typename Type>
  179. Type JsonNode::convertTo() const
  180. {
  181. Type result;
  182. JsonDetail::convert(result, *this);
  183. return result;
  184. }
  185. VCMI_LIB_NAMESPACE_END