@@ -52,6 +52,40 @@ struct StreamedJsonParserBase {
5252 int idxUnicode_{};
5353};
5454
55+ namespace jt {
56+
57+ template <typename K>
58+ using KeyType = StoreType<K, strhash<K>>;
59+
60+ template <typename T, typename K>
61+ concept JsonType = std::is_integral_v<std::remove_cvref_t <T>> ||
62+ std::is_floating_point_v<std::remove_cvref_t <T>> ||
63+ std::is_constructible_v<sstring<K>, T>;
64+
65+ template <typename T, typename K>
66+ concept JsonKeyType = std::convertible_to<T, simple_str<K>> ||
67+ std::same_as<std::remove_cvref_t <T>, KeyType<K>>;
68+
69+ template <typename T, typename K>
70+ concept JsonArraySource = requires (const T& t) {
71+ { t.empty () } -> std::same_as<bool >;
72+ { t.size () } -> std::same_as<size_t >;
73+ { *t.begin () } -> JsonType<K>;
74+ { *t.end () } -> JsonType<K>;
75+ };
76+
77+ template <typename T, typename K>
78+ concept JsonObjectSource = requires (const T& t) {
79+ { t.empty () } -> std::same_as<bool >;
80+ { t.size () } -> std::same_as<size_t >;
81+ { t.begin ()->first } -> JsonKeyType<K>;
82+ { t.end ()->first } -> JsonKeyType<K>;
83+ { t.begin ()->second } -> JsonType<K>;
84+ { t.end ()->second } -> JsonType<K>;
85+ };
86+
87+ } // namespace jt
88+
5589/* !
5690 * @brief Класс для представления json значения
5791 * @tparam K - тип символов
@@ -64,19 +98,31 @@ class JsonValueTempl : public Json {
6498 using ssType = simple_str<K>;
6599
66100 using json_value = JsonValueTempl<K>;
67- using json_object = std::shared_ptr< hashStrMap<K, JsonValueTempl<K> >>;
68- using json_array = std::shared_ptr<std:: vector<JsonValueTempl<K> >>;
69- using obj_type = typename json_object::element_type ;
70- using arr_type = typename json_array::element_type ;
101+ using obj_type = hashStrMap<K, JsonValueTempl<K>>;
102+ using arr_type = std::vector<JsonValueTempl<K>>;
103+ using json_object = std::shared_ptr<obj_type> ;
104+ using json_array = std::shared_ptr<arr_type> ;
71105
72106 // / Создает пустой объект с типом Undefined
73107 JsonValueTempl () : type_(Undefined) {}
74108 // / Конструктор копирования. Объекты и массивы копируются по ссылке
75109 JsonValueTempl (const JsonValueTempl& other);
76110 // / Конструктор перемещения
77111 JsonValueTempl (JsonValueTempl&& other) noexcept {
78- // Расчёт на то, что shared_ptr не содержит указателей на свои внутренности
79- memcpy ((void *)this , &other, sizeof (*this ));
112+ type_ = other.type_ ;
113+ switch (other.type_ ) {
114+ case Json::Text:
115+ new (&val_.text ) strType (std::move (other.val_ .text ));
116+ break ;
117+ case Json::Object:
118+ new (&val_.object ) json_object (std::move (other.val_ .object ));
119+ break ;
120+ case Json::Array:
121+ new (&val_.array ) json_array (std::move (other.val_ .array ));
122+ break ;
123+ default :
124+ memcpy (&val_, &other.val_ , sizeof (val_));
125+ }
80126 other.type_ = Undefined;
81127 }
82128 // / Деструктор
@@ -128,21 +174,40 @@ class JsonValueTempl : public Json {
128174 // / Конструктор для создания дефолтного значения с типом type
129175 JsonValueTempl (Type type);
130176
131- struct KeyInit : std::pair<const StoreType <K>, json_value> {
132- using base = std::pair<const StoreType <K>, json_value>;
133- KeyInit (const StoreType <K>& k, const json_value& v) : base(k, v){}
177+ struct KeyInit : std::pair<const jt::KeyType <K>, json_value> {
178+ using base = std::pair<const jt::KeyType <K>, json_value>;
179+ KeyInit (const jt::KeyType <K>& k, const json_value& v) : base(k, v){}
134180 KeyInit (ssType k, const json_value& v) : base(obj_type::toStoreType(k), v){}
135181 };
136182 using ObjectInit = std::initializer_list<KeyInit>;
137183 // / Конструктор из инициализатора для создания json::object: JsonValue v = {{"key1"_h, 1}, {"key2", "text"}, {"key3"_h, false}}; -> {"key1": 10, "key2": "text", "key3": false}
138184 JsonValueTempl (ObjectInit&& init) : type_(Object) {
139- new (&val_.object ) json_object (std::make_shared<obj_type>(std::move (reinterpret_cast <std::initializer_list<std::pair<const StoreType <K>, json_value>>&>(init))));
185+ new (&val_.object ) json_object (std::make_shared<obj_type>(std::move (reinterpret_cast <std::initializer_list<std::pair<const jt::KeyType <K>, json_value>>&>(init))));
140186 }
141187 using ArrayInit = std::initializer_list<json_value>;
142188 // / Конструктор из инициализатора для создания json::array: JsonValue json = {"key1", 12, false, Json::null, 1.25, true}; -> ["key1", 12, false, null, 1.25, true]
143189 JsonValueTempl (ArrayInit&& init) : type_(Array) {
144190 new (&val_.array ) json_array (std::make_shared<arr_type>(std::move (init)));
145191 }
192+ // / Конструктор из любого стандартного контейнера-массива, содержащего значения JSON.
193+ JsonValueTempl (jt::JsonArraySource<K> auto const & obj) : JsonValueTempl(emptyArray) {
194+ if (!obj.empty ()) {
195+ auto & arr = *as_array ();
196+ arr.reserve (obj.size ());
197+ for (const auto & e : obj) {
198+ arr.emplace_back (e);
199+ }
200+ }
201+ }
202+ // / Конструктор из любого стандартного контейнера с парами, содержащими строковый ключ в first и значение JSON в second.
203+ JsonValueTempl (jt::JsonObjectSource<K> auto const & obj) : JsonValueTempl(emptyObject) {
204+ if (!obj.empty ()) {
205+ auto & me = *as_object ();
206+ for (const auto & [f, s] : obj) {
207+ me.emplace (f, s);
208+ }
209+ }
210+ }
146211
147212 struct Clone {
148213 const json_value& from;
@@ -174,7 +239,6 @@ class JsonValueTempl : public Json {
174239 // / Значение object
175240 bool is_object () const { return type_ == Object; }
176241
177-
178242 // ----------------------------- Boolean -----------------------------------------------
179243
180244 // / Получить значение как boolean. В отладочной версии проверяется, что значение действительно boolean
@@ -352,7 +416,7 @@ class JsonValueTempl : public Json {
352416 }
353417
354418 // / Обращение к свойству константного объекта по ключу. Не создаёт новую пару при отсутствии ключа
355- template <typename T> requires (!std::is_integral_v<T>)
419+ template <jt::JsonKeyType<K> T>
356420 const json_value& at (T&& key) const {
357421 if (type_ == Object) {
358422 if (auto it = as_object ()->find (std::forward<T>(key)); it != as_object ()->end ())
@@ -362,13 +426,13 @@ class JsonValueTempl : public Json {
362426 }
363427
364428 // / Обращение к свойству константного объекта по ключу. Не создаёт новую пару при отсутствии ключа
365- template <typename T> requires (!std::is_integral_v<T>)
429+ template <jt::JsonKeyType<K> T>
366430 const json_value& operator [](T&& key) const {
367431 return at (std::forward<T>(key));
368432 }
369433
370434 // / Обращение к свойству константного объекта по ключам. Не создаёт новую пару при отсутствии ключа
371- template <typename T, typename ...Args> requires (!std::is_integral_v<T>)
435+ template <jt::JsonKeyType<K> T, typename ...Args>
372436 const json_value& operator ()(T&& key, Args&&...args) const {
373437 const json_value& res = at (std::forward<T>(key));
374438 if constexpr (sizeof ...(Args) == 0 ) {
@@ -380,7 +444,7 @@ class JsonValueTempl : public Json {
380444
381445 // / Обращение к свойству объекта по ключу. Создаёт новую пару при отсутствии ключа
382446 // / Если значение не объект, заменят его на объект
383- template <typename T> requires (!std::is_integral_v<T>)
447+ template <jt::JsonKeyType<K> T>
384448 json_value& operator [](T&& key) {
385449 if (type_ != Object) {
386450 assert (this != &UNDEFINED );
@@ -391,7 +455,7 @@ class JsonValueTempl : public Json {
391455
392456 // / Установка значения свойству объекта по ключу. Создаёт новую пару при отсутствии ключа
393457 // / Если значение не объект, заменят его на объект
394- template <typename Key, typename ... Args> requires (!std::is_integral_v<Key>)
458+ template <jt::JsonKeyType<K> Key, typename ... Args>
395459 json_value& set (Key&& key, Args&& ... args) {
396460 if (type_ != Object) {
397461 assert (this != &UNDEFINED );
@@ -444,10 +508,10 @@ class JsonValueTempl : public Json {
444508 }
445509
446510 // / Слияние с другим JSON. Если replace == true, то другой JSON имеет приоритет, если он не undefined.
447- // / Если оба объекта массивы, то другой массив дописывается к этому массиву.
511+ // / Если оба объекта массивы, то при append_arrays = true другой массив дописывается к этому массиву.
448512 // / Если оба JSONа объекты - то сливаются по ключам.
449513 // / Иначе другой JSON заменяет текущее значение.
450- void merge (const json_value& other, bool replace = true );
514+ void merge (const json_value& other, bool replace = true , bool append_arrays = false );
451515
452516 // / Распарсить текст с json.
453517 static std::tuple<json_value, JsonParseResult, unsigned , unsigned > parse (ssType jsonString);
0 commit comments