nfx-serialization 0.9.3
Cross-platform C++ JSON serialization library with extensible trait capabilities
Loading...
Searching...
No Matches
ContainersTraits.h
Go to the documentation of this file.
1/*
2 * MIT License
3 *
4 * Copyright (c) 2025 nfx
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
39
40#pragma once
41
43
44//=====================================================================
45// PerfectHashMap support - enabled only if header is available
46//=====================================================================
47
48#if __has_include( <nfx/containers/PerfectHashMap.h>)
49
50# include <nfx/containers/PerfectHashMap.h>
51
52namespace nfx::serialization::json
53{
57 template <typename TKey, typename TValue, typename HashType, HashType Seed, typename Hasher, typename KeyEqual>
58 struct SerializationTraits<nfx::containers::PerfectHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>>
59 {
66 static void fromDocument(
67 const Document& doc, nfx::containers::PerfectHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>& obj )
68 {
69 if( !doc.is<Array>( "" ) )
70 {
71 throw std::runtime_error{ "Cannot deserialize non-array JSON value into PerfectHashMap" };
72 }
73
74 // Collect key-value pairs for PerfectHashMap construction
75 std::vector<std::pair<TKey, TValue>> items;
76
77 // Get array and iterate using STL iterator
78 auto arrayOpt = doc.get<Array>( "" );
79 if( arrayOpt.has_value() )
80 {
81 for( const auto& pairDoc : arrayOpt.value() )
82 {
83 // Extract key - try different types
84 TKey key{};
85 bool keyFound = false;
86
87 if( pairDoc.contains( "key" ) )
88 {
89 // Try to deserialize key based on its actual JSON type
90 if constexpr( std::is_same_v<TKey, std::string> )
91 {
92 auto keyOpt = pairDoc.get<std::string>( "key" );
93 if( keyOpt )
94 {
95 key = *keyOpt;
96 keyFound = true;
97 }
98 }
99 else if constexpr( std::is_integral_v<TKey> && !std::is_same_v<TKey, bool> )
100 {
101 auto keyOpt = pairDoc.get<int64_t>( "key" );
102 if( keyOpt )
103 {
104 key = static_cast<TKey>( *keyOpt );
105 keyFound = true;
106 }
107 }
108 else if constexpr( std::is_floating_point_v<TKey> )
109 {
110 auto keyOpt = pairDoc.get<double>( "key" );
111 if( keyOpt )
112 {
113 key = static_cast<TKey>( *keyOpt );
114 keyFound = true;
115 }
116 }
117 else if constexpr( std::is_same_v<TKey, bool> )
118 {
119 auto keyOpt = pairDoc.get<bool>( "key" );
120 if( keyOpt )
121 {
122 key = *keyOpt;
123 keyFound = true;
124 }
125 }
126 }
127
128 // Extract value - try different types
129 TValue value{};
130 bool valueFound = false;
131
132 if( pairDoc.contains( "value" ) )
133 {
134 // Try to deserialize value based on its actual JSON type
135 if constexpr( std::is_same_v<TValue, std::string> )
136 {
137 auto valOpt = pairDoc.get<std::string>( "value" );
138 if( valOpt )
139 {
140 value = *valOpt;
141 valueFound = true;
142 }
143 }
144 else if constexpr( std::is_integral_v<TValue> && !std::is_same_v<TValue, bool> )
145 {
146 auto valOpt = pairDoc.get<int64_t>( "value" );
147 if( valOpt )
148 {
149 value = static_cast<TValue>( *valOpt );
150 valueFound = true;
151 }
152 }
153 else if constexpr( std::is_floating_point_v<TValue> )
154 {
155 auto valOpt = pairDoc.get<double>( "value" );
156 if( valOpt )
157 {
158 value = static_cast<TValue>( *valOpt );
159 valueFound = true;
160 }
161 }
162 else if constexpr( std::is_same_v<TValue, bool> )
163 {
164 auto valOpt = pairDoc.get<bool>( "value" );
165 if( valOpt )
166 {
167 value = *valOpt;
168 valueFound = true;
169 }
170 }
171 }
172
173 if( keyFound && valueFound )
174 {
175 items.emplace_back( std::move( key ), std::move( value ) );
176 }
177 }
178 }
179
180 obj = nfx::containers::PerfectHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>( std::move( items ) );
181 }
182
189 static void serialize(
190 const nfx::containers::PerfectHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>& obj,
191 nfx::json::Builder& builder )
192 {
193 builder.writeStartArray();
194
195 for( auto it = obj.begin(); it != obj.end(); ++it )
196 {
197 const auto& pair = *it;
198
199 builder.writeStartObject();
200
201 // Write key
202 builder.writeKey( "key" );
203 Serializer<TKey>{}.serializeValue( pair.first, builder );
204
205 // Write value
206 builder.writeKey( "value" );
207 Serializer<TValue>{}.serializeValue( pair.second, builder );
208
209 builder.writeEndObject();
210 }
211
212 builder.writeEndArray();
213 }
214 };
215} // namespace nfx::serialization::json
216
217#endif // __has_include(<nfx/containers/PerfectHashMap.h>)
218
219//=====================================================================
220// FastHashMap support - enabled only if header is available
221//=====================================================================
222
223#if __has_include( <nfx/containers/FastHashMap.h>)
224
225# include <nfx/containers/FastHashMap.h>
226
227namespace nfx::serialization::json
228{
232 template <typename TKey, typename TValue, typename HashType, HashType Seed, typename Hasher, typename KeyEqual>
233 struct SerializationTraits<nfx::containers::FastHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>>
234 {
241 static void fromDocument(
242 const Document& doc, nfx::containers::FastHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>& obj )
243 {
244 // Clear existing content
245 obj.clear();
246
247 // Check if it's an object format (standard JSON map representation)
248 if( doc.is<Object>( "" ) )
249 {
250 // Use Object iterator for object format
251 auto objectOpt = doc.get<Object>( "" );
252 if( objectOpt.has_value() )
253 {
254 for( const auto& [keyStr, valueDoc] : objectOpt.value() )
255 {
256 // Deserialize key (typically string, but support other types)
257 TKey key{};
258 if constexpr( std::is_same_v<TKey, std::string> )
259 {
260 key = keyStr;
261 }
262 else
263 {
264 Document keyDoc;
265 keyDoc.set( "", keyStr );
266 Serializer<TKey> keySerializer;
267 keySerializer.deserializeValue( keyDoc, key );
268 }
269
270 // Extract value
271 TValue value{};
272 Serializer<TValue> valueSerializer;
273 valueSerializer.deserializeValue( valueDoc, value );
274 obj.insertOrAssign( std::move( key ), std::move( value ) );
275 }
276 }
277 }
278 // Check if it's an array format (for backward compatibility)
279 else if( doc.is<Array>( "" ) )
280 {
281 // Get array and iterate using STL iterator
282 auto arrayOpt = doc.get<Array>( "" );
283 if( arrayOpt.has_value() )
284 {
285 for( const auto& pairDoc : arrayOpt.value() )
286 {
287 // Extract key - try different types
288 TKey key{};
289 bool keyFound = false;
290
291 if( pairDoc.contains( "key" ) )
292 {
293 // Try to deserialize key based on its actual JSON type
294 if constexpr( std::is_same_v<TKey, std::string> )
295 {
296 auto keyOpt = pairDoc.get<std::string>( "key" );
297 if( keyOpt )
298 {
299 key = *keyOpt;
300 keyFound = true;
301 }
302 }
303 else if constexpr( std::is_integral_v<TKey> && !std::is_same_v<TKey, bool> )
304 {
305 auto keyOpt = pairDoc.get<int64_t>( "key" );
306 if( keyOpt )
307 {
308 key = static_cast<TKey>( *keyOpt );
309 keyFound = true;
310 }
311 }
312 else if constexpr( std::is_floating_point_v<TKey> )
313 {
314 auto keyOpt = pairDoc.get<double>( "key" );
315 if( keyOpt )
316 {
317 key = static_cast<TKey>( *keyOpt );
318 keyFound = true;
319 }
320 }
321 else if constexpr( std::is_same_v<TKey, bool> )
322 {
323 auto keyOpt = pairDoc.get<bool>( "key" );
324 if( keyOpt )
325 {
326 key = *keyOpt;
327 keyFound = true;
328 }
329 }
330 }
331
332 // Extract value - try different types
333 TValue value{};
334 bool valueFound = false;
335
336 if( pairDoc.contains( "value" ) )
337 {
338 // Try to deserialize value based on its actual JSON type
339 if constexpr( std::is_same_v<TValue, std::string> )
340 {
341 auto valOpt = pairDoc.get<std::string>( "value" );
342 if( valOpt )
343 {
344 value = *valOpt;
345 valueFound = true;
346 }
347 }
348 else if constexpr( std::is_integral_v<TValue> && !std::is_same_v<TValue, bool> )
349 {
350 auto valOpt = pairDoc.get<int64_t>( "value" );
351 if( valOpt )
352 {
353 value = static_cast<TValue>( *valOpt );
354 valueFound = true;
355 }
356 }
357 else if constexpr( std::is_floating_point_v<TValue> )
358 {
359 auto valOpt = pairDoc.get<double>( "value" );
360 if( valOpt )
361 {
362 value = static_cast<TValue>( *valOpt );
363 valueFound = true;
364 }
365 }
366 else if constexpr( std::is_same_v<TValue, bool> )
367 {
368 auto valOpt = pairDoc.get<bool>( "value" );
369 if( valOpt )
370 {
371 value = *valOpt;
372 valueFound = true;
373 }
374 }
375 }
376
377 if( keyFound && valueFound )
378 {
379 obj.insertOrAssign( std::move( key ), std::move( value ) );
380 }
381 }
382 }
383 }
384 else
385 {
386 throw std::runtime_error{ "Cannot deserialize JSON value into FastHashMap: must be object or array" };
387 }
388 }
389
396 static void serialize(
397 const nfx::containers::FastHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>& obj,
398 nfx::json::Builder& builder )
399 {
400 builder.writeStartArray();
401
402 for( auto it = obj.begin(); it != obj.end(); ++it )
403 {
404 const auto& pair = *it;
405
406 builder.writeStartObject();
407
408 // Write key
409 builder.writeKey( "key" );
410 Serializer<TKey>{}.serializeValue( pair.first, builder );
411
412 // Write value
413 builder.writeKey( "value" );
414 Serializer<TValue>{}.serializeValue( pair.second, builder );
415
416 builder.writeEndObject();
417 }
418
419 builder.writeEndArray();
420 }
421 };
422} // namespace nfx::serialization::json
423
424#endif // __has_include(<nfx/containers/FastHashMap.h>)
425
426//=====================================================================
427// FastHashSet support - enabled only if header is available
428//=====================================================================
429
430#if __has_include( <nfx/containers/FastHashSet.h>)
431
432# include <nfx/containers/FastHashSet.h>
433
434namespace nfx::serialization::json
435{
439 template <typename TKey, typename HashType, HashType Seed, typename Hasher, typename KeyEqual>
440 struct SerializationTraits<nfx::containers::FastHashSet<TKey, HashType, Seed, Hasher, KeyEqual>>
441 {
447 static void fromDocument(
448 const Document& doc, nfx::containers::FastHashSet<TKey, HashType, Seed, Hasher, KeyEqual>& obj )
449 {
450 if( !doc.is<Array>( "" ) )
451 {
452 throw std::runtime_error{ "Cannot deserialize non-array JSON value into FastHashSet" };
453 }
454
455 // Clear existing content
456 obj.clear();
457
458 // Get array and iterate using STL iterator
459 auto arrayOpt = doc.get<Array>( "" );
460 if( arrayOpt.has_value() )
461 {
462 for( const auto& itemDoc : arrayOpt.value() )
463 {
464 TKey item;
465 Serializer<TKey>{}.deserializeValue( itemDoc, item );
466 obj.insert( std::move( item ) );
467 }
468 }
469 }
470
477 static void serialize(
478 const nfx::containers::FastHashSet<TKey, HashType, Seed, Hasher, KeyEqual>& obj,
479 nfx::json::Builder& builder )
480 {
481 builder.writeStartArray();
482
483 for( auto it = obj.begin(); it != obj.end(); ++it )
484 {
485 Serializer<TKey>{}.serializeValue( *it, builder );
486 }
487
488 builder.writeEndArray();
489 }
490 };
491} // namespace nfx::serialization::json
492
493#endif // __has_include(<nfx/containers/FastHashSet.h>)
494
495//=====================================================================
496// StackVector support - enabled only if header is available
497//=====================================================================
498
499#if __has_include( <nfx/containers/StackVector.h>)
500
501# include <nfx/containers/StackVector.h>
502
503namespace nfx::serialization::json
504{
508 template <typename T, std::size_t N>
509 struct SerializationTraits<nfx::containers::StackVector<T, N>>
510 {
516 static void fromDocument( const Document& doc, nfx::containers::StackVector<T, N>& obj )
517 {
518 if( !doc.is<Array>( "" ) )
519 {
520 throw std::runtime_error{ "Cannot deserialize non-array JSON value into StackVector" };
521 }
522
523 // Clear existing content
524 obj.clear();
525
526 // Get array and iterate using STL iterator
527 auto arrayOpt = doc.get<Array>( "" );
528 if( arrayOpt.has_value() )
529 {
530 for( const auto& elementDoc : arrayOpt.value() )
531 {
532 // Deserialize the element using a temporary serializer
533 T element{};
534 Serializer<T> elementSerializer;
535 elementSerializer.deserializeValue( elementDoc, element );
536
537 obj.push_back( std::move( element ) );
538 }
539 }
540 }
541
548 static void serialize( const nfx::containers::StackVector<T, N>& obj, nfx::json::Builder& builder )
549 {
550 builder.writeStartArray();
551
552 for( const auto& element : obj )
553 {
554 Serializer<T>{}.serializeValue( element, builder );
555 }
556
557 builder.writeEndArray();
558 }
559 };
560} // namespace nfx::serialization::json
561
562#endif // __has_include(<nfx/containers/StackVector.h>)
563
564//=====================================================================
565// OrderedHashMap support - enabled only if header is available
566//=====================================================================
567
568#if __has_include( <nfx/containers/OrderedHashMap.h>)
569
570# include <nfx/containers/OrderedHashMap.h>
571
572namespace nfx::serialization::json
573{
577 template <typename TKey, typename TValue, typename HashType, HashType Seed, typename Hasher, typename KeyEqual>
578 struct SerializationTraits<nfx::containers::OrderedHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>>
579 {
586 static void fromDocument(
587 const Document& doc, nfx::containers::OrderedHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>& obj )
588 {
589 if( !doc.is<Array>( "" ) )
590 {
591 throw std::runtime_error{ "Cannot deserialize non-array JSON value into OrderedHashMap" };
592 }
593
594 obj.clear();
595
596 // Get array and iterate using STL iterator
597 auto arrayOpt = doc.get<Array>( "" );
598 if( arrayOpt.has_value() )
599 {
600 for( const auto& pairDoc : arrayOpt.value() )
601 {
602 // Extract key - try different types
603 TKey key{};
604 bool keyFound = false;
605
606 if( pairDoc.contains( "key" ) )
607 {
608 // Try to deserialize key based on its actual JSON type
609 if constexpr( std::is_same_v<TKey, std::string> )
610 {
611 auto keyOpt = pairDoc.get<std::string>( "key" );
612 if( keyOpt )
613 {
614 key = *keyOpt;
615 keyFound = true;
616 }
617 }
618 else if constexpr( std::is_integral_v<TKey> && !std::is_same_v<TKey, bool> )
619 {
620 auto keyOpt = pairDoc.get<int64_t>( "key" );
621 if( keyOpt )
622 {
623 key = static_cast<TKey>( *keyOpt );
624 keyFound = true;
625 }
626 }
627 else if constexpr( std::is_floating_point_v<TKey> )
628 {
629 auto keyOpt = pairDoc.get<double>( "key" );
630 if( keyOpt )
631 {
632 key = static_cast<TKey>( *keyOpt );
633 keyFound = true;
634 }
635 }
636 else if constexpr( std::is_same_v<TKey, bool> )
637 {
638 auto keyOpt = pairDoc.get<bool>( "key" );
639 if( keyOpt )
640 {
641 key = *keyOpt;
642 keyFound = true;
643 }
644 }
645 }
646
647 // Extract value - try different types
648 TValue value{};
649 bool valueFound = false;
650
651 if( pairDoc.contains( "value" ) )
652 {
653 // Try to deserialize value based on its actual JSON type
654 if constexpr( std::is_same_v<TValue, std::string> )
655 {
656 auto valOpt = pairDoc.get<std::string>( "value" );
657 if( valOpt )
658 {
659 value = *valOpt;
660 valueFound = true;
661 }
662 }
663 else if constexpr( std::is_integral_v<TValue> && !std::is_same_v<TValue, bool> )
664 {
665 auto valOpt = pairDoc.get<int64_t>( "value" );
666 if( valOpt )
667 {
668 value = static_cast<TValue>( *valOpt );
669 valueFound = true;
670 }
671 }
672 else if constexpr( std::is_floating_point_v<TValue> )
673 {
674 auto valOpt = pairDoc.get<double>( "value" );
675 if( valOpt )
676 {
677 value = static_cast<TValue>( *valOpt );
678 valueFound = true;
679 }
680 }
681 else if constexpr( std::is_same_v<TValue, bool> )
682 {
683 auto valOpt = pairDoc.get<bool>( "value" );
684 if( valOpt )
685 {
686 value = *valOpt;
687 valueFound = true;
688 }
689 }
690 }
691
692 if( keyFound && valueFound )
693 {
694 obj.insertOrAssign( std::move( key ), std::move( value ) );
695 }
696 }
697 }
698 }
699
706 static void serialize(
707 const nfx::containers::OrderedHashMap<TKey, TValue, HashType, Seed, Hasher, KeyEqual>& obj,
708 Builder& builder )
709 {
710 builder.writeStartArray();
711
712 for( const auto& [key, value] : obj )
713 {
714 builder.writeStartObject();
715 builder.write( "key", key );
716 builder.write( "value", value );
717 builder.writeEndObject();
718 }
719
720 builder.writeEndArray();
721 }
722 };
723} // namespace nfx::serialization::json
724
725#endif // __has_include(<nfx/containers/OrderedHashMap.h>)
726
727//=====================================================================
728// OrderedHashSet support - enabled only if header is available
729//=====================================================================
730
731#if __has_include( <nfx/containers/OrderedHashSet.h>)
732
733# include <nfx/containers/OrderedHashSet.h>
734
735namespace nfx::serialization::json
736{
740 template <typename TKey, typename HashType, HashType Seed, typename Hasher, typename KeyEqual>
741 struct SerializationTraits<nfx::containers::OrderedHashSet<TKey, HashType, Seed, Hasher, KeyEqual>>
742 {
749 static void fromDocument(
750 const Document& doc, nfx::containers::OrderedHashSet<TKey, HashType, Seed, Hasher, KeyEqual>& obj )
751 {
752 if( !doc.is<Array>( "" ) )
753 {
754 throw std::runtime_error{ "Cannot deserialize non-array JSON value into OrderedHashSet" };
755 }
756
757 obj.clear();
758
759 // Get array and iterate using STL iterator
760 auto arrayOpt = doc.get<Array>( "" );
761 if( arrayOpt.has_value() )
762 {
763 for( const auto& elementDoc : arrayOpt.value() )
764 {
765 // Extract element - try different types
766 TKey element{};
767 bool elementFound = false;
768
769 // Try to deserialize element based on its actual JSON type
770 if constexpr( std::is_same_v<TKey, std::string> )
771 {
772 auto elemOpt = elementDoc.get<std::string>( "" );
773 if( elemOpt )
774 {
775 element = *elemOpt;
776 elementFound = true;
777 }
778 }
779 else if constexpr( std::is_integral_v<TKey> && !std::is_same_v<TKey, bool> )
780 {
781 auto elemOpt = elementDoc.get<int64_t>( "" );
782 if( elemOpt )
783 {
784 element = static_cast<TKey>( *elemOpt );
785 elementFound = true;
786 }
787 }
788 else if constexpr( std::is_floating_point_v<TKey> )
789 {
790 auto elemOpt = elementDoc.get<double>( "" );
791 if( elemOpt )
792 {
793 element = static_cast<TKey>( *elemOpt );
794 elementFound = true;
795 }
796 }
797 else if constexpr( std::is_same_v<TKey, bool> )
798 {
799 auto elemOpt = elementDoc.get<bool>( "" );
800 if( elemOpt )
801 {
802 element = *elemOpt;
803 elementFound = true;
804 }
805 }
806
807 if( elementFound )
808 {
809 obj.insert( std::move( element ) );
810 }
811 }
812 }
813 }
814
821 static void serialize(
822 const nfx::containers::OrderedHashSet<TKey, HashType, Seed, Hasher, KeyEqual>& obj, Builder& builder )
823 {
824 builder.writeStartArray();
825
826 for( const auto& element : obj )
827 {
828 builder.write( element );
829 }
830
831 builder.writeEndArray();
832 }
833 };
834} // namespace nfx::serialization::json
835
836#endif // __has_include(<nfx/containers/OrderedHashSet.h>)
837
838//=====================================================================
839// StackHashMap support - enabled only if header is available
840//=====================================================================
841
842#if __has_include( <nfx/containers/StackHashMap.h>)
843
844# include <nfx/containers/StackHashMap.h>
845
846namespace nfx::serialization::json
847{
851 template <typename TKey, typename TValue, std::size_t N, typename KeyEqual>
852 struct SerializationTraits<nfx::containers::StackHashMap<TKey, TValue, N, KeyEqual>>
853 {
860 static void fromDocument( const Document& doc, nfx::containers::StackHashMap<TKey, TValue, N, KeyEqual>& obj )
861 {
862 if( !doc.is<Array>( "" ) )
863 {
864 throw std::runtime_error{ "Cannot deserialize non-array JSON value into StackHashMap" };
865 }
866
867 // Clear existing content
868 obj.clear();
869
870 // Get array and iterate using STL iterator
871 auto arrayOpt = doc.get<Array>( "" );
872 if( arrayOpt.has_value() )
873 {
874 for( const auto& pairDoc : arrayOpt.value() )
875 {
876 // Extract key
877 auto keyDoc = pairDoc.get<Document>( "key" );
878 if( !keyDoc )
879 {
880 throw std::runtime_error{ "Missing 'key' field in StackHashMap array element" };
881 }
882 TKey key{};
883 Serializer<TKey>{}.deserializeValue( *keyDoc, key );
884
885 // Extract value
886 auto valueDoc = pairDoc.get<Document>( "value" );
887 if( !valueDoc )
888 {
889 throw std::runtime_error{ "Missing 'value' field in StackHashMap array element" };
890 }
891 TValue value{};
892 Serializer<TValue>{}.deserializeValue( *valueDoc, value );
893
894 obj.insertOrAssign( std::move( key ), std::move( value ) );
895 }
896 }
897 }
898
905 static void serialize(
906 const nfx::containers::StackHashMap<TKey, TValue, N, KeyEqual>& obj, nfx::json::Builder& builder )
907 {
908 builder.writeStartArray();
909
910 obj.forEach( [&builder]( const TKey& key, const TValue& value ) {
911 builder.writeStartObject();
912
913 // Write key
914 builder.writeKey( "key" );
915 Serializer<TKey>{}.serializeValue( key, builder );
916
917 // Write value
918 builder.writeKey( "value" );
919 Serializer<TValue>{}.serializeValue( value, builder );
920
921 builder.writeEndObject();
922 } );
923
924 builder.writeEndArray();
925 }
926 };
927} // namespace nfx::serialization::json
928
929#endif // __has_include(<nfx/containers/StackHashMap.h>)
930
931//=====================================================================
932// StackHashSet support - enabled only if header is available
933//=====================================================================
934
935#if __has_include( <nfx/containers/StackHashSet.h>)
936
937# include <nfx/containers/StackHashSet.h>
938
939namespace nfx::serialization::json
940{
944 template <typename TKey, std::size_t N, typename KeyEqual>
945 struct SerializationTraits<nfx::containers::StackHashSet<TKey, N, KeyEqual>>
946 {
952 static void fromDocument( const Document& doc, nfx::containers::StackHashSet<TKey, N, KeyEqual>& obj )
953 {
954 if( !doc.is<Array>( "" ) )
955 {
956 throw std::runtime_error{ "Cannot deserialize non-array JSON value into StackHashSet" };
957 }
958
959 // Clear existing content
960 obj.clear();
961
962 // Get array and iterate using STL iterator
963 auto arrayOpt = doc.get<Array>( "" );
964 if( arrayOpt.has_value() )
965 {
966 for( const auto& itemDoc : arrayOpt.value() )
967 {
968 TKey item{};
969 Serializer<TKey>{}.deserializeValue( itemDoc, item );
970 obj.insert( std::move( item ) );
971 }
972 }
973 }
974
981 static void serialize(
982 const nfx::containers::StackHashSet<TKey, N, KeyEqual>& obj, nfx::json::Builder& builder )
983 {
984 builder.writeStartArray();
985
986 obj.forEach( [&builder]( const TKey& element ) { Serializer<TKey>{}.serializeValue( element, builder ); } );
987
988 builder.writeEndArray();
989 }
990 };
991} // namespace nfx::serialization::json
992
993#endif // __has_include(<nfx/containers/StackHashSet.h>)
Templated JSON serializer with compile-time type mapping.
Serialization traits template (forward declaration).
static void fromDocument(const Document &doc, T &obj)
Convert Document to object (deserialization).