├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .gitlab-ci.yml ├── .tipi ├── deps ├── id └── opts ├── INSTALL.md ├── LICENSE ├── README.md ├── examples ├── from_json.cpp └── to_json.cpp ├── pre ├── enums │ └── to_underlying.hpp ├── fusion │ └── for_each_member.hpp ├── json │ ├── detail │ │ ├── dejsonizer.hpp │ │ ├── get_type_name_as_string.hpp │ │ ├── jsonizer.hpp │ │ └── sfinae_enabler.hpp │ ├── from_json.hpp │ ├── mapping.hpp │ ├── to_json.hpp │ └── traits │ │ ├── is_associative_container.hpp │ │ ├── is_container.hpp │ │ ├── is_jsonizable.hpp │ │ └── is_string.hpp └── variant │ ├── apply_visitor.hpp │ ├── for_each_type.hpp │ └── traits │ └── is_std_variant.hpp └── test ├── dejsonize_test.cpp ├── variant_for_each_type.cpp └── wasm_boost_test.hpp /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | # This workflow is triggered on pushes to the repository. 3 | on: [pull_request] 4 | 5 | jobs: 6 | build-wasm: 7 | name: build-wasm 8 | runs-on: ubuntu-latest 9 | container: tipibuild/tipi-ubuntu 10 | steps: 11 | - name: checkout 12 | uses: actions/checkout@v2 13 | - name: nxxm builds project 14 | run: | 15 | tipi . --dont-upgrade --verbose --test all -t wasm-cxx17 16 | build-clang-linux: 17 | name: build-clang-linux 18 | runs-on: ubuntu-latest 19 | container: tipibuild/tipi-ubuntu 20 | steps: 21 | - name: checkout 22 | uses: actions/checkout@v2 23 | - name: nxxm builds project 24 | run: | 25 | tipi . --dont-upgrade --verbose --test all -t linux-cxx17 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | build-linux: 2 | image: registry.gitlab.com/nxxm/nxxm/ci/ubuntu-cpp:latest 3 | script: 4 | - mkdir build/ && cd build/ 5 | - cmake .. -DCMAKE_BUILD_TYPE=MinSizeRel -DUNIT_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=deps/polly/gcc-7-cxx17.cmake 6 | - cmake --build . --config MinSizeRel 7 | - ctest . -C MinSizeRel --verbose 8 | 9 | build-macOS: 10 | tags: 11 | - macOS 12 | script: 13 | - mkdir build/ && cd build/ 14 | - cmake .. -DCMAKE_BUILD_TYPE=MinSizeRel -DUNIT_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=deps/polly/clang-cxx17.cmake 15 | - cmake --build . --config MinSizeRel 16 | - ctest . -C MinSizeRel --verbose 17 | 18 | build-win10: 19 | tags: 20 | - win10 21 | script: 22 | - set PreferredToolArchitecture=x64 23 | - mkdir build && cd build 24 | - cmake .. -DCMAKE_BUILD_TYPE=MinSizeRel -DUNIT_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=deps/polly/vs-15-2017-cxx17.cmake 25 | - cmake --build . --config MinSizeRel 26 | - ctest . -C MinSizeRel --verbose 27 | -------------------------------------------------------------------------------- /.tipi/deps: -------------------------------------------------------------------------------- 1 | { 2 | "nlohmann/json" : { "@" : "v3.11.2", "x" : ["benchmarks"] } 3 | , "boostorg/boost" : { 4 | "@" : "boost-1.80.0" 5 | , "u" : true 6 | , "opts" : "set(BOOST_INCLUDE_LIBRARIES fusion)" 7 | , "packages" : ["boost_fusion"] 8 | , "targets" : ["Boost::fusion"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.tipi/id: -------------------------------------------------------------------------------- 1 | {"host_name":"github.com","org_name":"cpp-pre","repo_name":"json"} -------------------------------------------------------------------------------- /.tipi/opts: -------------------------------------------------------------------------------- 1 | set(BOOST_INCLUDE_LIBRARIES fusion) 2 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | 2 | # Installing pre::json 3 | json can be installed in three ways : 4 | 5 | * [Copy paste in your project](#copy-paste-in-your-project) 6 | * [Install](#install) 7 | * [Install without dependencies](#install-without-dependencies) 8 | 9 | ## Copy paste in your project 10 | 1. Copy this folder in your project 11 | 2. Add the following to your include path : 12 | 13 | ### GCC / Clang / MSVC 14 | ``` 15 | -I json/ \ 16 | -I json/deps/boostorg/algorithm/include/ \ 17 | -I json/deps/boostorg/array/include/ \ 18 | -I json/deps/boostorg/assert/include/ \ 19 | -I json/deps/boostorg/bind/include/ \ 20 | -I json/deps/boostorg/concept_check/include/ \ 21 | -I json/deps/boostorg/config/include/ \ 22 | -I json/deps/boostorg/container_hash/include/ \ 23 | -I json/deps/boostorg/core/include/ \ 24 | -I json/deps/boostorg/detail/include/ \ 25 | -I json/deps/boostorg/exception/include/ \ 26 | -I json/deps/boostorg/function/include/ \ 27 | -I json/deps/boostorg/function_types/include/ \ 28 | -I json/deps/boostorg/functional/include/ \ 29 | -I json/deps/boostorg/fusion/include/ \ 30 | -I json/deps/boostorg/integer/include/ \ 31 | -I json/deps/boostorg/io/include/ \ 32 | -I json/deps/boostorg/iterator/include/ \ 33 | -I json/deps/boostorg/move/include/ \ 34 | -I json/deps/boostorg/mpl/include/ \ 35 | -I json/deps/boostorg/numeric_conversion/include/ \ 36 | -I json/deps/boostorg/optional/include/ \ 37 | -I json/deps/boostorg/predef/include/ \ 38 | -I json/deps/boostorg/preprocessor/include/ \ 39 | -I json/deps/boostorg/range/include/ \ 40 | -I json/deps/boostorg/regex/include/ \ 41 | -I json/deps/boostorg/smart_ptr/include/ \ 42 | -I json/deps/boostorg/static_assert/include/ \ 43 | -I json/deps/boostorg/system/include/ \ 44 | -I json/deps/boostorg/test/include/ \ 45 | -I json/deps/boostorg/throw_exception/include/ \ 46 | -I json/deps/boostorg/timer/include/ \ 47 | -I json/deps/boostorg/tuple/include/ \ 48 | -I json/deps/boostorg/type_index/include/ \ 49 | -I json/deps/boostorg/type_traits/include/ \ 50 | -I json/deps/boostorg/typeof/include/ \ 51 | -I json/deps/boostorg/utility/include/ \ 52 | -I json/deps/boostorg/winapi/include/ \ 53 | -I json/deps/nlohmann/json/include/ \ 54 | ``` 55 | 56 | ## Install 57 | Install the library 58 | ```sh 59 | mkdir build/ && cd build/ 60 | cmake .. 61 | make install 62 | ``` 63 | 64 | You can tweak destination with `-DCMAKE_INSTALL_PREFIX=/install/path` to change the default `/usr/local`. 65 | 66 | ## If you use CMake : 67 | ```cmake 68 | find_package(json REQUIRED) 69 | add_executable(app your_code.cpp) 70 | target_link_libraries(app pre::json) 71 | ``` 72 | 73 | ## If you don't use CMake : 74 | Add to your include path : 75 | ``` 76 | INSTALL_PREFIX/include/json/deps/ 77 | INSTALL_PREFIX/include/ 78 | ``` 79 | 80 | ## Install without dependencies 81 | Install the library 82 | ```sh 83 | mkdir build/ && cd build/ 84 | cmake .. -DINGLUED=OFF 85 | make install 86 | ``` 87 | 88 | This library was built with [`#inglued <>`](https://github.com/header-only/inglued) therefore it forwards dependencies with it, but you might prefer the use of your own deps, therefore simply disable them via `INGLUED=OFF`. 89 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2018 Damien Buhl alias daminetreg (damien.buhl@lecbna.org) 2 | 3 | Boost Software License - Version 1.0 - August 17th, 2003 4 | 5 | Permission is hereby granted, free of charge, to any person or organization 6 | obtaining a copy of the software and accompanying documentation covered by 7 | this license (the "Software") to use, reproduce, display, distribute, 8 | execute, and transmit the Software, and to prepare derivative works of the 9 | Software, and to permit third-parties to whom the Software is furnished to 10 | do so, all subject to the following: 11 | 12 | The copyright notices in the Software and this entire statement, including 13 | the above license grant, this restriction and the following disclaimer, 14 | must be included in all copies of the Software, in whole or in part, and 15 | all derivative works of the Software, unless such copies or derivative 16 | works are solely in the form of machine-executable object code generated by 17 | a source language processor. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![pipeline status](https://git.lecbna.org/cpp-pre/json/badges/master/pipeline.svg)](https://git.lecbna.org/cpp-pre/json/commits/master) *for win10, macOS & linux.* 2 | # pre::from_ or to_ json 3 | 4 | [de]Serializes any json object or value to a C++ type with the magic of compile time reflection. 5 | 6 | ## Examples 7 | 8 | See : 9 | - [Deserialize JSON to a C++ aggregate](examples/from_json.cpp) 10 | - [Serialize a C++ aggregate to JSON](examples/to_json.cpp) 11 | - [Extensive Tests](test/dejsonize_test.cpp) 12 | 13 | ```cpp 14 | #include 15 | #include
 
16 | 
17 | // Your C++ type
18 | struct customer {
19 |   std::string name;
20 |   size_t money_spent; 
21 |   std::vector interests;
22 | };
23 | 
24 | // Reflection for the fields you want to load from json
25 | BOOST_FUSION_ADAPT_STRUCT(customer,
26 |   name,
27 |   money_spent,
28 |   interests)
29 | 
30 | ...
31 | 
32 | std::string string_from_network = 
33 |   "{\"interests\":[\"sport articles\"], \"money_spent\":50, \"name\":\"Mrs. Fraulein\"}";
34 | 
35 | // Here you get your C++ type
36 | customer my_customer =
37 |   pre::json::from_json(string_from_network);
38 | 
39 | std::cout << "Customer " << my_customer.name << " spent " <<
40 |   my_customer.money_spent << std::endl;
41 | ```
42 | 
43 | ### Supported types 
44 | 
45 |   - [Any Integral Types](http://en.cppreference.com/w/cpp/types/is_integral)
46 |   - [std::basic_string, std::string...](http://en.cppreference.com/w/cpp/string/basic_string)
47 |   - [Aggregate/struct adapted with Boost.Fusion](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/adapted/adapt_struct.html)
48 |   - [Any Container](http://en.cppreference.com/w/cpp/concept/AssociativeContainer) ( i.e. std::vector, std::list...)
49 |   - [Any AssociativeContainer](http://en.cppreference.com/w/cpp/concept/AssociativeContainer) ( i.e. std::map, std::set, std::multimap...)
50 |   - [std::optional](http://en.cppreference.com/w/cpp/utility/optional)
51 |   - [std::variant](http://en.cppreference.com/w/cpp/utility/variant)
52 |   - [std::chrono::duration](http://en.cppreference.com/w/cpp/chrono/duration)
53 | 
54 | 
55 | ## License
56 | [Boost Software License](./LICENSE).
57 | 
58 | Please give copyright notice : 
59 | ```
60 | Copyright (c) 2012-2018 Damien Buhl alias daminetreg (damien.buhl@lecbna.org)
61 | ```
62 | 
63 | 


--------------------------------------------------------------------------------
/examples/from_json.cpp:
--------------------------------------------------------------------------------
 1 | #include 
 2 | #include 
 
 3 | #include 
 4 | #include 
 5 | 
 6 |  
 7 | struct customer {
 8 |   std::string name;
 9 |   size_t money_spent; 
10 |   std::vector interests;
11 |   std::optional is_private;  // this property shall be mapped to the "private" key in the json
12 |   std::vector numbers;
13 | };
14 | 
15 | BOOST_FUSION_ADAPT_STRUCT(customer,
16 |   name,
17 |   money_spent,
18 |   interests,
19 |   is_private,
20 |   numbers)
21 | 
22 | int main() {
23 | 
24 | 
25 |   std::string string_to_deserialize = 
26 |     "{\"interests\":[\"sport articles\"], \"money_spent\":50, \"name\":\"Mrs. Fraulein\", \"private\": true, \"numbers\": [1,2,3]}";
27 | 
28 |   // classic deserialization
29 |   {
30 |     customer my_customer = pre::json::from_json(string_to_deserialize);
31 | 
32 |     std::cout << "Customer " << my_customer.name << " spent " <<
33 |       my_customer.money_spent << std::endl;
34 |   }
35 | 
36 |   // with mapping deserialization
37 |   {
38 |     customer my_customer = pre::json::from_json(string_to_deserialize, [](nlohmann::json& jdoc) {
39 |       jdoc["is_private"] = jdoc["private"];
40 |       jdoc.erase("private");
41 |     });
42 | 
43 |     std::cout << "Customer " << my_customer.name << " spent " <<
44 |       my_customer.money_spent << " is private:" << std::to_string(my_customer.is_private.value()) << std::endl;
45 |   }
46 | 
47 |   // with mapping helpers
48 |   {
49 |     customer my_customer = pre::json::from_json(string_to_deserialize, [](nlohmann::json& jdoc) {
50 |       pre::json::remap_property(jdoc, "private", "is_private");
51 |     });
52 | 
53 |     std::cout << "Customer " << my_customer.name << " spent " <<
54 |       my_customer.money_spent << " is private:" << std::to_string(my_customer.is_private.value()) << std::endl;
55 |   }
56 | 
57 |   // with mapping and json_pointer helpers
58 |   {
59 |     std::string string_to_deserialize = 
60 |     "{\"interests\":[\"sport articles\"], \"money_spent\":50, \"name\":\"Mrs. Fraulein\", \"private\": true, \"numbers\": [1,2,3]}";
61 | 
62 |     customer my_customer = pre::json::from_json(string_to_deserialize, [](nlohmann::json& jdoc) {
63 |       pre::json::remap_property(jdoc, "/private"_json_pointer, "/is_private"_json_pointer);
64 |       pre::json::remap_property(jdoc, "/numbers/0"_json_pointer, "/numbersNew/2"_json_pointer);
65 |       pre::json::remap_property(jdoc, "/money_spent"_json_pointer, "/numbers/0"_json_pointer);
66 |       jdoc["money_spent"] = 0;
67 |       std::cout << jdoc.dump(2) << std::endl; 
68 |     });
69 |   } 
70 | 
71 |   return 0;
72 | }
73 | 


--------------------------------------------------------------------------------
/examples/to_json.cpp:
--------------------------------------------------------------------------------
 1 | #include 
 2 | #include 
 3 | #include 
 4 | 
 5 | struct customer {
 6 |   std::string name;
 7 |   size_t money_spent;
 8 |   std::vector interests;
 9 |   bool is_private;
10 | };
11 | 
12 | BOOST_FUSION_ADAPT_STRUCT(customer,
13 |   name,
14 |   money_spent,
15 |   interests,
16 |   is_private)
17 | 
18 | 
19 | int main() {
20 | 
21 |   {
22 |     customer my_customer{
23 |       "Mr. Dupond",
24 |       1000,
25 |       {"sport articles", "food", "tools"},
26 |       true
27 |     };
28 | 
29 |     std::cout << pre::json::to_json(my_customer) << std::endl;
30 | 
31 |     // with remapping
32 |     std::cout << "With property 'is_private' mapped to 'private':\n" 
33 |       << pre::json::to_json(
34 |         my_customer, 
35 |         [](auto &jdoc) { 
36 |           pre::json::remap_property(jdoc, "/is_private"_json_pointer, "/private"_json_pointer);
37 |         }) 
38 |       << std::endl;
39 |   }
40 | 
41 | 
42 |   return 0;
43 | }
44 | 


--------------------------------------------------------------------------------
/pre/enums/to_underlying.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_ENUMS_TO_UNDERLYING_HPP
 2 | #define PRE_ENUMS_TO_UNDERLYING_HPP
 3 | 
 4 | #include 
 5 | 
 6 | namespace pre { namespace enums {
 7 | 
 8 |   /**
 9 |    * \return The enum typed value casted to it's underlying_type.
10 |    */
11 |   template 
12 |   typename std::underlying_type::type to_underlying(E e) {
13 |       return static_cast::type>(e);
14 |   }
15 | 
16 | }}  
17 | 
18 | #endif
19 | 


--------------------------------------------------------------------------------
/pre/fusion/for_each_member.hpp:
--------------------------------------------------------------------------------
  1 | #ifndef PRE_FUSION_FOR_EACH_MEMBER_HPP
  2 | #define PRE_FUSION_FOR_EACH_MEMBER_HPP
  3 | 
  4 | #include 
  5 | #include 
  6 | 
  7 | #include  
  8 | 
  9 | #include 
 10 | #include 
 11 | #include 
 12 | #include 
 13 | #include 
 14 | #include 
 15 | #include 
 16 | #include 
 17 | #include 
 18 | #include 
 19 | 
 20 | namespace pre { namespace fusion {
 21 | 
 22 | namespace detail {
 23 | 
 24 | 
 25 |   template 
 26 |   inline void
 27 |   for_each_member_linear(First const& first, 
 28 |       Last const& last, 
 29 |       F const& f,
 30 |       Sequence&,
 31 |       boost::mpl::true_) {}
 32 | 
 33 |   template ::type,
 37 |       boost::fusion::struct_tag
 38 |     >::value
 39 |   >::type* = nullptr>
 40 |   inline void
 41 |   for_each_member_linear(First & first, 
 42 |       Last const& last,
 43 |       F const& f,
 44 |       Sequence& seq,
 45 |       boost::mpl::false_) {
 46 | 
 47 |       f(
 48 | 				boost::fusion::extension::struct_member_name<
 49 | 					typename std::remove_cv< typename First::seq_type>::type , First::index::value
 50 | 				>::call(), 
 51 | 				*first
 52 | 			);
 53 | 
 54 |       for_each_member_linear(
 55 |           next(first), 
 56 |           last,
 57 |           f,
 58 |           seq,
 59 |           boost::fusion::result_of::equal_to< typename boost::fusion::result_of::next::type, Last>()
 60 |       );
 61 |   }
 62 | 
 63 | 
 64 |  template ::type,
 68 |       boost::fusion::boost_tuple_tag
 69 |     >::value
 70 |   >::type* = nullptr>
 71 |   inline void
 72 |   for_each_member_linear(First & first, 
 73 |       Last const& last,
 74 |       F const& f,
 75 |       Sequence& seq,
 76 |       boost::mpl::false_) {
 77 | 
 78 |       auto index = boost::fusion::result_of::distance<
 79 |                      typename boost::fusion::result_of::begin::type, 
 80 |                      First
 81 |                    >::type::value; 
 82 |       std::string name =  typeid(decltype(*first)).name();
 83 | 
 84 |       f(
 85 | 				 (name + std::string("_") + std::to_string(index)).data(), 
 86 | 				*first
 87 | 			);
 88 | 
 89 |       for_each_member_linear(
 90 |           next(first), 
 91 |           last,
 92 |           f,
 93 |           seq,
 94 |           boost::fusion::result_of::equal_to< typename boost::fusion::result_of::next::type, Last>()
 95 |       );
 96 |   }
 97 | 
 98 |   template 
 99 |   inline void
100 |   for_each_member(Sequence& seq, F const& f) {
101 | 
102 |     detail::for_each_member_linear(
103 |       boost::fusion::begin(seq), 
104 |       boost::fusion::end(seq), 
105 |       f, 
106 |       seq,
107 |       boost::fusion::result_of::equal_to<
108 |         typename boost::fusion::result_of::begin::type, 
109 |         typename boost::fusion::result_of::end::type>()
110 |     );
111 |   }
112 | 
113 | }
114 | 
115 |   template 
116 |   inline void
117 |   for_each_member(Sequence& seq, F f) {
118 |     detail::for_each_member(seq, f);
119 |   }
120 |  
121 | }}
122 | 
123 | #endif
124 | 


--------------------------------------------------------------------------------
/pre/json/detail/dejsonizer.hpp:
--------------------------------------------------------------------------------
  1 | #ifndef PRE_JSON_DETAIL_DEJSONIZER_HPP
  2 | #define PRE_JSON_DETAIL_DEJSONIZER_HPP
  3 | 
  4 | #include 
  5 | #include 
  6 | 
  7 | #include 
  8 | #include 
  9 | 
 10 | #include 
 11 | 
 12 | #include 
 13 | 
 14 | #include 
 15 | #include 
 16 | #include 
 17 | 
 18 | #include 
 19 | 
 20 | namespace pre { namespace json { namespace detail {
 21 | 
 22 |   struct dejsonizer {
 23 | 
 24 |     dejsonizer(const nlohmann::json& json_object) : 
 25 |       _json_object(json_object) {}
 26 | 
 27 |     template 
 28 |     void operator()(const char* name, T& value) const {
 29 | 
 30 |       if (_json_object.find(name) != std::end(_json_object)) {
 31 |         dejsonizer dejsonizer(_json_object.at(name));
 32 |         dejsonizer(value);
 33 |       } else {
 34 |         throw std::runtime_error(
 35 |           "Missing key " + std::string(name) + " in JSON Object : " + _json_object.dump());
 36 |       }
 37 |     }
 38 | 
 39 |     template 
 40 |     void operator()(const char* name, std::optional& value) const {
 41 |       // std::optional doesn't need to be in the json object
 42 |       if (_json_object.find(name) != std::end(_json_object)) {
 43 |         dejsonizer dejsonizer(_json_object.at(name));
 44 |         dejsonizer(value);
 45 |       }
 46 |     }
 47 | 
 48 |     template
 49 |     void operator()(std::optional& value) const {
 50 |       // std::optional doesn't need to be in the json object
 51 |       if (!_json_object.empty()) {
 52 |         dejsonizer dejsonizer(_json_object);
 53 | 
 54 |         T optional_value;
 55 |         dejsonizer(optional_value);
 56 |         value = optional_value;
 57 |       }
 58 |     }
 59 | 
 60 |     template* = nullptr>
 62 |     void operator()(T& value) const {
 63 |       if (_json_object.is_object()) {
 64 |         pre::fusion::for_each_member(value, *this);
 65 |       } else {
 66 |         throw std::runtime_error("The JSON Object " + _json_object.dump() + " isn't an object that we can map to an internal type");
 67 |       }
 68 |     }
 69 | 
 70 |     template
 71 |     struct variant_checker {
 72 |       
 73 |       variant_checker(const nlohmann::json& json_object, TVariant& value) : _json_object(json_object), value(value) {
 74 |       };
 75 | 
 76 |       template< typename U > void operator()(U&& x) {
 77 |         if (!successed) {
 78 |             auto struct_it = _json_object.find("struct");
 79 |             
 80 |             if ( (struct_it != _json_object.end()) && 
 81 |                 (*struct_it == get_type_name_as_string()) ) {
 82 | 
 83 |               dejsonizer dejsonizer(_json_object);
 84 |               U test_value;
 85 |               dejsonizer(test_value);
 86 |               successed = true;
 87 |               value = test_value;
 88 |             }
 89 |         }
 90 |       }
 91 | 
 92 |       private:
 93 |         const nlohmann::json& _json_object;
 94 |         TVariant &value;
 95 |         bool successed = false;
 96 |     };
 97 | 
 98 |     template* = nullptr>
100 |     void operator()(T& value) const {
101 |       pre::variant::for_each_type( value, variant_checker(_json_object, value) );
102 |     }
103 | 
104 |     template::value>::type* = nullptr>
106 |     void operator()(T& value) const {
107 |       // XXX : How could we safe range check enum assignement ?
108 |       value = static_cast(_json_object.get::type>());
109 |     }
110 | 
111 |     template* = nullptr>
113 |     void operator()(T& value) const {
114 |       value = T{_json_object.get()};
115 |     }
116 | 
117 |     template* = nullptr>
119 |     void operator()(T& value) const {
120 |       //TODO: Better diagnostic, current exception is : std::exception::what: type must be number, but is string, we should reoutput the json object in this case. 
121 |       value = _json_object.get();
122 |     }
123 | 
124 |     template* = nullptr>
126 |     void operator()(T& value) const {
127 |       if (_json_object.is_array()) {
128 | 
129 |         value.clear(); //XXX: Needed to clear if already somehow full ?
130 |         // XXX: Not supported by all containers : value.reserve(array.size());
131 |         for (auto entry_json : _json_object) { 
132 |           typename T::value_type entry_deser;
133 |           dejsonizer dejsonizer(entry_json);
134 |           dejsonizer(entry_deser);
135 |           value.push_back(entry_deser);
136 |         }
137 | 
138 |       } else {
139 |         throw std::runtime_error("Expected " + _json_object.dump() + " to be a json array.");
140 |       }
141 | 
142 |     }
143 | 
144 |     template* = nullptr>
146 |     void operator()(T& value) const {
147 |       if (_json_object.is_object()) {
148 | 
149 |         value.clear();
150 | 
151 |         for (nlohmann::json::const_iterator it = _json_object.begin(); it != _json_object.end(); ++it) {
152 |           typename T::mapped_type entry_deser;
153 |           dejsonizer dejsonizer(it.value());
154 |           dejsonizer(entry_deser);
155 |           value[it.key()] = entry_deser;
156 |         }
157 | 
158 |       } else {
159 |         throw std::runtime_error("Expected " + _json_object.dump() + " to be a json object.");
160 |       }
161 |     }
162 |       
163 |     private:
164 |       const nlohmann::json& _json_object; // XXX: Invert to be the same as jsonizer
165 |     
166 |   };
167 | 
168 | }}}
169 | 
170 | #endif
171 | 


--------------------------------------------------------------------------------
/pre/json/detail/get_type_name_as_string.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_JSON_DETAIL_GET_TYPE_NAME_AS_STRING_HPP
 2 | #define PRE_JSON_DETAIL_GET_TYPE_NAME_AS_STRING_HPP
 3 | 
 4 | #include 
 5 | #include 
 6 | 
 7 | namespace pre { namespace json { namespace detail {
 8 | 
 9 |   template
10 |   inline std::string get_type_name_as_string() {
11 |   
12 |     using namespace boost::algorithm;
13 |     auto pretty_name = boost::typeindex::type_id().pretty_name();
14 |     if (starts_with(pretty_name, "struct ")) {
15 |       return replace_first_copy(pretty_name, "struct ", "");
16 |     } else if (starts_with(pretty_name, "class ")) {
17 |       return replace_first_copy(pretty_name, "class ", "");
18 |     } else {
19 |       return pretty_name;
20 |     }
21 |   }
22 | }}}
23 | 
24 | #endif
25 | 


--------------------------------------------------------------------------------
/pre/json/detail/jsonizer.hpp:
--------------------------------------------------------------------------------
  1 | #ifndef PRE_JSON_DETAIL_JSONIZER_HPP
  2 | #define PRE_JSON_DETAIL_JSONIZER_HPP
  3 | 
  4 | #include 
  5 | #include 
  6 | 
  7 | #include 
  8 | 
  9 | #include 
 10 | 
 11 | #include 
 12 | 
 13 | #include 
 14 | #include 
 15 | #include 
 16 | #include 
 17 | 
 18 | //TODO: What about tuples ?
 19 | //TODO: What about normal union?
 20 | 
 21 | namespace pre { namespace json { namespace detail {
 22 | 
 23 |   struct jsonizer {
 24 | 
 25 |     jsonizer(nlohmann::json& json_object) 
 26 |       : _json_object(json_object),
 27 |       _disambiguate_struct(false) {}
 28 | 
 29 |     template
 30 |     void operator()(const char* name, const T& value) const {
 31 |       nlohmann::json json_subobject;
 32 |       jsonizer subjsonizer(json_subobject);
 33 |       subjsonizer(value);
 34 | 
 35 |       _json_object[std::string(name)] = json_subobject;
 36 |     }
 37 | 
 38 |     template
 39 |     void operator()(const char* name, const std::optional& value) const {
 40 |       if (value != std::nullopt) {
 41 |         this->operator()(name, value.value());
 42 |       }
 43 |     }
 44 | 
 45 |     template
 46 |     void operator()(const std::optional& value) const {
 47 |       if (value != std::nullopt) {
 48 |         jsonizer subjsonizer(_json_object);
 49 |         subjsonizer(*value);
 50 |       } else {
 51 |         _json_object = nullptr;
 52 |       }
 53 |     }
 54 | 
 55 |     template* = nullptr>
 57 |     void operator()(const T& value) const {
 58 | 
 59 |       if (_disambiguate_struct) {
 60 |         _json_object["struct"] =  get_type_name_as_string();
 61 |         _disambiguate_struct = false; // Do it only once in hierarchy
 62 |       }
 63 |       pre::fusion::for_each_member(value, *this);
 64 |     }
 65 | 
 66 |     template* = nullptr>
 68 |     void operator()(const T& value) const {
 69 |       boost::fusion::for_each(value, *this);
 70 |       // HMMMMM ???
 71 |     }
 72 | 
 73 |     template* = nullptr>
 75 |     void operator()(const T& value) const {
 76 |       // struct has to be disambiguated in case of variant.
 77 |       _disambiguate_struct = true; 
 78 |       pre::variant::apply_visitor(*this, value);
 79 |     }
 80 | 
 81 |     template::value>::type* = nullptr>
 83 |     void operator()(const T& value) const {
 84 |       _json_object = pre::enums::to_underlying(value);
 85 |     }
 86 | 
 87 |     template* = nullptr>
 89 |     void operator()(const T& value) const {
 90 |       _json_object = value.count();
 91 |     }
 92 | 
 93 |     template* = nullptr>
 95 |     void operator()(const T& value) const {
 96 |       _json_object = value;
 97 |     }
 98 | 
 99 |     template* = nullptr>
101 |     void operator()(const T& value) const {
102 |       _json_object = nlohmann::json::array();
103 |       for (const auto& each : value) {
104 |         nlohmann::json json_subobject;
105 |         jsonizer subjsonizer(json_subobject);
106 |         subjsonizer(each);
107 |         _json_object.push_back(json_subobject); 
108 |       }
109 |     }
110 | 
111 |     template* = nullptr>
113 |     void operator()(const T& value) const {
114 |       _json_object = nlohmann::json::object();
115 |       for (const auto& each : value) {
116 |         nlohmann::json json_subobject;
117 |         jsonizer subjsonizer(json_subobject);
118 |         subjsonizer(each.second);
119 |         _json_object[each.first] = json_subobject; 
120 |       }
121 |     }
122 | 
123 |     
124 |     private:
125 |       nlohmann::json& _json_object;
126 |       mutable bool _disambiguate_struct;
127 |     
128 |   };
129 | 
130 | 
131 | }}}
132 | 
133 | #endif
134 | 


--------------------------------------------------------------------------------
/pre/json/detail/sfinae_enabler.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_JSON_DETAIL_SFINAE_ENABLER_HPP
 2 | #define PRE_JSON_DETAIL_SFINAE_ENABLER_HPP
 3 | 
 4 | #include 
 5 | 
 6 | #include 
 7 | #include 
 8 | #include 
 9 | 
10 | #include 
11 | #include 
12 | #include 
13 | #include 
14 | 
15 | #include 
16 | 
17 | 
18 | namespace pre { namespace json { namespace detail {
19 | 
20 |     template
21 |     using enable_if_is_chrono_duration_t = typename std::enable_if< 
22 |       std::is_same, T>::value 
23 |     >::type;
24 | 
25 |     template
26 |     using enable_if_is_directly_serializable_t = typename std::enable_if<
27 |       std::is_fundamental::value || traits::is_string::value
28 |     ,T>::type;
29 | 
30 |     template
31 |     using enable_if_is_variant_t = typename std::enable_if<
32 |       pre::variant::traits::is_std_variant::value
33 |     ,T>::type;
34 | 
35 |     template
36 |     using enable_if_is_other_sequence_and_not_variant_t = typename std::enable_if<
37 |       boost::fusion::traits::is_sequence::value
38 |       && !std::is_same< 
39 |             typename boost::fusion::traits::tag_of::type, 
40 |             boost::fusion::struct_tag
41 |           >::value
42 |       && !enable_if_is_variant_t::value 
43 |     ,T>::type;
44 | 
45 |     template
46 |     using enable_if_is_adapted_struct_t = typename std::enable_if< 
47 |       std::is_same<
48 |         typename boost::fusion::traits::tag_of::type, 
49 |         boost::fusion::struct_tag
50 |       >::value
51 |     ,T>::type;
52 | 
53 | 
54 |     template
55 |     using enable_if_is_container_t = typename std::enable_if<
56 |       traits::is_container::value
57 |     ,T>::type;
58 | 
59 |     template
60 |     using enable_if_is_associative_container_t = typename std::enable_if<
61 |       traits::is_associative_container::value 
62 |     ,T>::type;
63 | 
64 | 
65 | }}}
66 | 
67 | #endif
68 | 


--------------------------------------------------------------------------------
/pre/json/from_json.hpp:
--------------------------------------------------------------------------------
  1 | #ifndef PRE_JSON_FROM_JSON_HPP
  2 | #define PRE_JSON_FROM_JSON_HPP
  3 | 
  4 | #include 
  5 | 
  6 | namespace pre { namespace json {
  7 | 
  8 |   /**
  9 |    * \brief Deserialize any json object or value in a C++ type.
 10 |    * \param T The result type wanted from the deserialization. that will be filled from the given json_object.
 11 |    * \param serialized_json json to deserialize
 12 |    *
 13 |    * Deserialize any json object or value in a C++ type.
 14 |    *
 15 |    * The function throws an std::exception if a mandatory member 
 16 |    * isn't found, but doesn't in the case of std::optional.
 17 |    *
 18 |    * The type has to be supported, or adapted with [BOOST\_FUSION\_ADAPT\_STRUCT](http://www.boost.org/doc/libs/release/libs/fusion/doc/html/fusion/adapted/adapt_struct.html).
 19 |    *
 20 |    * See below for supported types.
 21 |    * 
 22 |    * ### Example
 23 |    *  
 24 |    * \code{.cpp}
 25 |    *  #include 
 26 |    *  #include 
 
 27 |    *  
 28 |    *  struct customer {
 29 |    *    std::string name;
 30 |    *    size_t money_spent; 
 31 |    *    std::vector interests;
 32 |    *  };
 33 |    *
 34 |    *  BOOST_FUSION_ADAPT_STRUCT(customer,
 35 |    *    name,
 36 |    *    money_spent,
 37 |    *    interests)
 38 |    *  
 39 |    *  ...
 40 |    *
 41 |    *  std::string string_to_deserialize = 
 42 |    *    "{\"interests\":[\"sport articles\"], \"money_spent\":50, \"name\":\"Mrs. Fraulein\"}";
 43 |    *
 44 |    *  customer my_customer = pre::json::from_json(string_to_deserialize);
 45 |    *
 46 |    *  std::cout << "Customer " << my_customer.name << " spent " <<
 47 |    *    my_customer.money_spent << std::endl;
 48 |    *
 49 |    * \endcode
 50 |    *
 51 |    *   - [Full example](../examples/from_json.cpp)
 52 |    *   - [Extended examples](../test/dejsonize_test.cpp)
 53 |    *
 54 |    * ### Supported types 
 55 |    *
 56 |    *   - [Any Integral Types](http://en.cppreference.com/w/cpp/types/is_integral)
 57 |    *   - [std::basic_string, std::string...](http://en.cppreference.com/w/cpp/string/basic_string)
 58 |    *   - [Aggregate/struct adapted with Boost.Fusion](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/adapted/adapt_struct.html)
 59 |    *   - [Any Container](http://en.cppreference.com/w/cpp/concept/AssociativeContainer) ( i.e. std::vector, std::list...)
 60 |    *   - [Any AssociativeContainer](http://en.cppreference.com/w/cpp/concept/AssociativeContainer) ( i.e. std::map, std::set, std::multimap...)
 61 |    *   - [std::optional](http://en.cppreference.com/w/cpp/utility/optional)
 62 |    *   - [std::variant](http://en.cppreference.com/w/cpp/utility/variant)
 63 |    *   - [std::chrono::duration](http://en.cppreference.com/w/cpp/chrono/duration)
 64 |    *
 65 |    * \return the type wanted if it succeed find all member and value in the json.
 66 |    */
 67 |   template
 68 |   T from_json(const std::string& serialized_json) {
 69 |     const nlohmann::json json_object = nlohmann::json::parse(serialized_json);
 70 |     T object;
 71 |     detail::dejsonizer dejsonizer(json_object);
 72 |     dejsonizer(object);
 73 |     return object;
 74 |   }
 75 | 
 76 |   /**
 77 |    * \brief Same as pre::json::from_json(const std::string&) but with an added mapper function
 78 |    */
 79 |   template
 80 |   T from_json(const std::string& serialized_json, std::function mapper) {
 81 |     nlohmann::json json_object = nlohmann::json::parse(serialized_json);
 82 |     mapper(json_object);  // does whatever mapping is required
 83 |     T object;
 84 |     detail::dejsonizer dejsonizer(json_object);
 85 |     dejsonizer(object);
 86 |     return object;
 87 |   }
 88 | 
 89 |   /**
 90 |    * \brief Same as pre::json::from_json(const std::string&) but directly with a JSON.
 91 |    */
 92 |   template
 93 |   T from_json(const nlohmann::json& json_object) {
 94 |     T object;
 95 |     detail::dejsonizer dejsonizer(json_object);
 96 |     dejsonizer(object);
 97 |     return object;
 98 |   }
 99 | }}
100 | 
101 | #endif
102 | 


--------------------------------------------------------------------------------
/pre/json/mapping.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_JSON_MAPPING_HPP
 2 | #define PRE_JSON_MAPPING_HPP
 3 | 
 4 | #include 
 5 | #include 
 6 | 
 7 | namespace pre { 
 8 |     namespace json {
 9 | 
10 | 
11 |         /**
12 |          * @brief "Rername" a json key in the JSON object
13 |          * 
14 |          * @param jdoc 
15 |          * @param psource source key name
16 |          * @param pdest destination key name
17 |          */
18 |         inline void remap_property(nlohmann::json& jdoc, std::string psource, std::string pdest) {
19 |             jdoc[pdest] = jdoc[psource];
20 |             jdoc.erase(psource);
21 |         }
22 | 
23 |         inline void remap_property(nlohmann::json& jdoc, 
24 |             nlohmann::json::json_pointer psource, 
25 |             nlohmann::json::json_pointer pdest
26 |         ) {
27 |             // get reference to parent of JSON pointer ptr
28 |             const auto original_psource = psource;
29 |             const auto last_path = psource.back();
30 |             psource.pop_back();
31 |             auto& parent = jdoc.at(psource);
32 | 
33 |             // remove child
34 |             if (parent.is_object())
35 |             {
36 |                 auto it = parent.find(last_path);
37 |                 if (it != parent.end())
38 |                 {
39 |                     jdoc[pdest] = jdoc[original_psource];
40 |                     parent.erase(it);
41 |                 }
42 |                 else
43 |                 {
44 |                     throw std::runtime_error("Could not find json key at: " + original_psource.to_string());
45 |                 }
46 |             }
47 |             else if (parent.is_array())
48 |             {
49 |                 auto ix_deletion = std::stoi(last_path);
50 |                 auto value = jdoc[original_psource]; // copy source before deleting it
51 | 
52 |                 if(ix_deletion >= parent.size()) {
53 |                     throw std::runtime_error("Index out of range when accessing array at: " + original_psource.to_string());
54 |                 }
55 | 
56 |                 parent.erase(ix_deletion);   // no need to range check manually, erase() does it already
57 |                 jdoc[pdest] = value;
58 |                 
59 |             }
60 |         }
61 |     }
62 | }
63 | 
64 | #endif


--------------------------------------------------------------------------------
/pre/json/to_json.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_JSON_TO_JSON_HPP
 2 | #define PRE_JSON_TO_JSON_HPP
 3 | 
 4 | #include 
 5 | 
 6 | namespace pre { namespace json {
 7 | 
 8 |   /**
 9 |    * \brief Serialize to a JSON object any C++ object of any type, even your own types. 
10 |    * \param T Any of the Supported Types.
11 |    * \param value A value adapted with [BOOST\_FUSION\_ADAPT\_STRUCT](http://www.boost.org/doc/libs/release/libs/fusion/doc/html/fusion/adapted/adapt_struct.html).
12 |    *        This value can be any aggregate with nested aggregate or any C++ types.
13 |    *
14 |    * Serialize to a JSON object any C++ object of any type, even your own types. 
15 |    *
16 |    * It uses type traits introspection as well as Boost.Fusion reflection information to generate JSON from any types.
17 |    *
18 |    * ### Example 
19 |    *  
20 |    * \code{.cpp}
21 |    *   #include 
22 |    *   #include 
 
23 |    *  
24 |    *   struct customer {
25 |    *     std::string name;
26 |    *     size_t money_spent; 
27 |    *     std::vector interests;
28 |    *   };
29 |    *
30 |    *   BOOST_FUSION_ADAPT_STRUCT(customer,
31 |    *     name,
32 |    *     money_spent,
33 |    *     interests)
34 |    *  
35 |    *  ...
36 |    *
37 |    *  customer my_customer{
38 |    *    "Mr. Dupond",
39 |    *    1000,
40 |    *    {"sport articles", "food", "tools"}
41 |    *  };
42 |    *
43 |    *  std::cout << pre::json::to_json(my_customer) << std::endl;
44 |    * \endcode
45 |    * 
46 |    *   - [Full example](../examples/to_json.cpp)
47 |    *   - [Extended examples](../test/dejsonize_test.cpp)
48 |    *
49 |    * ### Supported types 
50 |    *
51 |    *   - [Any Integral Types](http://en.cppreference.com/w/cpp/types/is_integral)
52 |    *   - [std::basic_string, std::string...](http://en.cppreference.com/w/cpp/string/basic_string)
53 |    *   - [Aggregate/struct adapted with Boost.Fusion](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/adapted/adapt_struct.html)
54 |    *   - [Any Container](http://en.cppreference.com/w/cpp/concept/AssociativeContainer) ( i.e. std::vector, std::list...)
55 |    *   - [Any AssociativeContainer](http://en.cppreference.com/w/cpp/concept/AssociativeContainer) ( i.e. std::map, std::set, std::multimap...)
56 |    *   - [std::optional](http://en.cppreference.com/w/cpp/utility/optional)
57 |    *   - [std::variant](http://en.cppreference.com/w/cpp/utility/variant)
58 |    *   - [std::chrono::duration](http://en.cppreference.com/w/cpp/chrono/duration)
59 |    *
60 |    *
61 |    * \return An [nlohmann::json](https://github.com/nlohmann/json/) object directly streamable to std::cout or convertible to string.
62 |    */
63 |   template
64 |   nlohmann::json to_json(const T& value) {
65 |     nlohmann::json json_object;
66 |     detail::jsonizer jsonizer(json_object);
67 |     jsonizer(value);
68 |     return json_object;
69 |   }
70 | 
71 |   /**
72 |    * \brief Same as pre::json::to_json(const T&) but with a post serialization mapper function
73 |    * 
74 |    * \tparam T 
75 |    * \param value 
76 |    * \param mapper 
77 |    * \return An [nlohmann::json](https://github.com/nlohmann/json/) object directly streamable to std::cout or convertible to string.
78 |    */
79 |   template
80 |   nlohmann::json to_json(const T& value, std::function mapper) {
81 |     nlohmann::json json_object;
82 |     detail::jsonizer jsonizer(json_object);
83 |     jsonizer(value);
84 |     mapper(json_object);
85 |     return json_object;
86 |   }
87 | }}
88 | 
89 | #endif
90 | 


--------------------------------------------------------------------------------
/pre/json/traits/is_associative_container.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_JSON_TRAITS_IS_ASSOCIATIVE_CONTAINER_HPP
 2 | #define PRE_JSON_TRAITS_IS_ASSOCIATIVE_CONTAINER_HPP
 3 | 
 4 | #include 
 5 | #include 
 6 | #include 
 7 | #include 
 8 | 
 9 | 
10 | namespace pre { namespace json { namespace traits {
11 | 
12 |   /**
13 |    * Credits to relaxx
14 |    * See http://stackoverflow.com/a/31532326/271781 
15 |    *
16 |    */
17 |   template
18 |   struct to_void
19 |   {
20 |       typedef void type;
21 |   };
22 | 
23 |   template 
24 |   struct is_associative_container : std::false_type {};
25 | 
26 |   template 
27 |   struct is_associative_container::type > : std::true_type{};
28 | 
29 |   template 
30 |   struct is_multi_container : std::false_type {};
31 | 
32 |   template 
33 |   struct is_unique_container : std::conditional::value, std::false_type, std::true_type>::type{};
34 | 
35 |   template 
36 |   struct is_unordered_container : std::false_type {};
37 | 
38 |   template 
39 |   struct is_ordered_container : std::conditional::value, std::false_type, std::true_type>::type{};
40 | 
41 |   template 
42 |   struct is_multi_container> : std::true_type {};
43 | 
44 |   template 
45 |   struct is_multi_container> : std::true_type{};
46 | 
47 |   template 
48 |   struct is_multi_container> : std::true_type{};
49 | 
50 |   template 
51 |   struct is_multi_container> : std::true_type{};
52 | 
53 |   template 
54 |   struct is_unordered_container> : std::true_type{};
55 | 
56 |   template 
57 |   struct is_unordered_container> : std::true_type{};
58 | 
59 |   template 
60 |   struct is_unordered_container> : std::true_type{};
61 | 
62 |   template 
63 |   struct is_unordered_container> : std::true_type{};
64 | 
65 | }}}
66 | 
67 | #endif
68 | 


--------------------------------------------------------------------------------
/pre/json/traits/is_container.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_JSON_TRAITS_IS_CONTAINER_HPP
 2 | #define PRE_JSON_TRAITS_IS_CONTAINER_HPP
 3 | 
 4 | #include 
 5 | #include 
 6 | 
 7 | namespace pre { namespace json { namespace traits {
 8 | 
 9 |   /**
10 |    * \return whether the given Container is a standard container
11 |    */
12 |   template 
13 |   struct is_container : std::false_type { };
14 | 
15 |   template  struct is_container > : std::true_type { };
16 |   template  struct is_container > : std::true_type { };
17 | 
18 | }}}
19 | 
20 | #endif
21 | 


--------------------------------------------------------------------------------
/pre/json/traits/is_jsonizable.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_JSON_TRAITS_IS_JSONIZABLE_HPP
 2 | #define PRE_JSON_TRAITS_IS_JSONIZABLE_HPP
 3 | 
 4 | #include 
 5 | #include 
 6 | #include 
 7 | #include 
 8 | 
 9 | #include 
10 | #include 
11 | 
12 | #include 
13 | #include 
14 | #include 
15 | 
16 | #include 
17 | #include 
18 | #include 
19 | #include 
20 | 
21 | namespace pre { namespace json { namespace traits {
22 | 
23 |   namespace mpl = boost::mpl;
24 |   namespace fusion = boost::fusion; 
25 | 
26 |   template 
27 |   struct is_jsonizable : std::false_type {};
28 | 
29 | 
30 |   // Any container of jsonizable
31 |   template 
32 |   struct is_jsonizable::type,
36 |         typename is_jsonizable::type
37 |       >::value
38 |     >::type> : std::true_type {};
39 | 
40 |   // Any associative container with a key of type compatible to string and a jsonizable value
41 |   template 
42 |   struct is_jsonizable::type,
46 |         typename std::is_convertible::type,
47 |         typename is_jsonizable::type
48 |       >::value
49 |     >::type> : std::true_type {};
50 | 
51 |   template 
52 |   struct is_jsonizable::type,
57 | 
58 |         // Any boost variant
59 |         typename pre::variant::traits::is_std_variant::type,
60 | 
61 |         // Integral types
62 |         typename mpl::or_<
63 |           typename std::is_convertible::type,
64 |           typename std::is_arithmetic::type
65 |         >::type
66 |       >::value
67 |     >::type> : std::true_type {};
68 | 
69 | }}}
70 | 
71 | #endif
72 | 


--------------------------------------------------------------------------------
/pre/json/traits/is_string.hpp:
--------------------------------------------------------------------------------
 1 | #ifndef PRE_JSON_TRAITS_IS_STRING_HPP
 2 | #define PRE_JSON_TRAITS_IS_STRING_HPP
 3 | 
 4 | #include 
 5 | 
 6 | namespace pre { namespace json { namespace traits {
 7 | 
 8 |   template 
 9 |   struct is_string : std::false_type {};
10 | 
11 |   template 
12 |   struct is_string > : std::true_type {};
13 | 
14 | }}}
15 | 
16 | #endif
17 | 


--------------------------------------------------------------------------------
/pre/variant/apply_visitor.hpp:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | #include 
 4 | #include 
 5 | 
 6 | #include 
 7 | 
 8 | namespace pre::variant { 
 9 | 
10 |   // std variant
11 | 
12 |   template::value >::type* = nullptr>
14 |   inline auto apply_visitor(const VisitorType& visitor, const VariantType& variant) -> decltype(std::visit(visitor,variant)) {
15 |     return std::visit(visitor,variant);
16 |   } 
17 | 
18 |   template::value >::type* = nullptr>
20 |   inline auto apply_visitor(const VisitorType& visitor, VariantType& variant) -> decltype(std::visit(visitor,variant)) {
21 |     return std::visit(visitor,variant);
22 |   } 
23 | 
24 |   template::value >::type* = nullptr>
26 |   inline auto apply_visitor(VisitorType& visitor, const VariantType& variant) -> decltype(std::visit(visitor,variant)) {
27 |     return std::visit(visitor,variant);
28 |   } 
29 | 
30 |   template::value >::type* = nullptr>
32 |   inline auto apply_visitor(VisitorType& visitor, VariantType& variant)  -> decltype(std::visit(visitor,variant)) {
33 |     return std::visit(visitor,variant);
34 |   }
35 | 
36 | 
37 | }
38 | 


--------------------------------------------------------------------------------
/pre/variant/for_each_type.hpp:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | namespace pre::variant {
 4 | 
 5 |   template< template class Variant, class F, class... Types>
 6 |   inline void for_each_type( Variant& variant, F&& f) {
 7 |     (void)std::initializer_list{(std::ref(f)(std::forward(Types{})),0)...};
 8 |   }
 9 | 
10 |   template< template class Variant, class F, class... Types>
11 |   inline void for_each_type( const Variant& variant, F&& f) {
12 |     (void)std::initializer_list{(std::ref(f)(std::forward(Types{})),0)...};
13 |   }
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/pre/variant/traits/is_std_variant.hpp:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | #include 
 4 | 
 5 | namespace pre::variant::traits {
 6 | 
 7 |   /**
 8 |    * \return whether the given Container is a standard container
 9 |    */
10 |   template 
11 |   struct is_std_variant : std::false_type { };
12 | 
13 |   template  struct is_std_variant > : std::true_type { };
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/test/dejsonize_test.cpp:
--------------------------------------------------------------------------------
  1 | #define BOOST_TEST_MODULE dejsonize_test
  2 | #include 
  3 | 
  4 | #include "wasm_boost_test.hpp"
  5 | 
  6 | #include 
  7 | #include 
  8 | #include 
  9 | 
 10 | #include 
 11 | #include 
 12 | #include 
 13 | 
 14 | #include 
 15 | 
 16 | #include 
 17 | 
 18 | #include 
 19 | #include 
 20 | #include 
 21 | 
 22 | namespace datamodel {
 23 | 
 24 |   using boost::fusion::operator==;
 25 |   using boost::fusion::operator!=;
 26 | 
 27 |   typedef size_t years;
 28 | 
 29 |   struct skill {
 30 |     std::string skill_name;
 31 |     years experience;
 32 |   };
 33 | }
 34 | 
 35 | BOOST_FUSION_ADAPT_STRUCT(datamodel::skill,
 36 |     skill_name,
 37 |     experience)
 38 | 
 39 | 
 40 | BOOST_FUSION_DEFINE_STRUCT((datamodel), customer,
 41 |     (std::string, name)
 42 |     (size_t, age)
 43 |     (std::vector, friends_id)
 44 |     (std::list, skillset)
 45 |     )
 46 | 
 47 | namespace datamodel {
 48 | 
 49 |   struct sales_assitant {
 50 | 
 51 |     sales_assitant() {}
 52 | 
 53 |     sales_assitant(
 54 |       std::string nickname,
 55 |       size_t salary,
 56 |       customer main_customer) 
 57 |       : nickname(nickname),
 58 |          salary(salary),
 59 |          main_customer(main_customer) {
 60 |      }
 61 | 
 62 |     std::string nickname;
 63 |     size_t salary;
 64 |     customer main_customer; 
 65 |   };
 66 | }
 67 | 
 68 | BOOST_FUSION_ADAPT_STRUCT(datamodel::sales_assitant,
 69 |   nickname,
 70 |   salary,
 71 |   main_customer)
 72 | 
 73 | BOOST_AUTO_TEST_CASE (traits) {
 74 | 
 75 |   struct non_adapted_struct {
 76 |     int dummy;
 77 |     int dummy2;
 78 |   };
 79 | 
 80 |   static_assert(pre::json::traits::is_jsonizable::type::value, "datamodel::customer should be jsonizable.");
 81 |   static_assert(pre::json::traits::is_jsonizable::type::value, "int should be jsonizable.");
 82 |   static_assert(pre::json::traits::is_jsonizable::type::value, "float should be jsonizable.");
 83 |   static_assert(pre::json::traits::is_jsonizable::type::value, "float should be jsonizable.");
 84 |   static_assert(pre::json::traits::is_jsonizable::type::value, "std::string should be jsonizable.");
 85 |   static_assert(pre::json::traits::is_jsonizable< std::map >::type::value, "std::map should be jsonizable.");
 86 |   static_assert(pre::json::traits::is_jsonizable< std::vector >::type::value, "should NOT be jsonizable");
 87 |   static_assert(pre::json::traits::is_jsonizable< std::vector >::type::value, "should NOT be jsonizable");
 88 | 
 89 |   static_assert(pre::json::traits::is_jsonizable>::type::value == false , "std::map should NOT be jsonizable.");
 90 |   static_assert(pre::json::traits::is_jsonizable::type::value == false , "non_adapted_struct should NOT be jsonizable.");
 91 |   static_assert(pre::json::traits::is_jsonizable< std::vector >::type::value == false, "should NOT be jsonizable");
 92 | 
 93 | }
 94 | 
 95 | BOOST_AUTO_TEST_CASE (composedtype) {
 96 | 
 97 | 
 98 |   // Testing a customer structure
 99 |   datamodel::customer customer {
100 |     "Mr. Dupond",
101 |     43,
102 |     {1,5},
103 |     {datamodel::skill{"C++", 10}, datamodel::skill{"GML", 20}, datamodel::skill{"Linux", 2}}
104 |   };
105 | 
106 |   auto json_customer = pre::json::to_json(customer);
107 |   std::cout << json_customer.dump(2) << std::endl;
108 | 
109 |   auto customer_parsed = pre::json::from_json(json_customer);
110 |   BOOST_REQUIRE(customer_parsed == customer);
111 | 
112 |   auto json_customer_after_reserialize = pre::json::to_json(customer);
113 |   std::cout << json_customer_after_reserialize.dump(2) << std::endl;
114 |   BOOST_REQUIRE(json_customer == json_customer_after_reserialize);
115 | 
116 |   // testing an adapted skill alone from plain json
117 |   nlohmann::json obj {
118 |     {"skill_name", "GML"},
119 |     {"experience", 10}
120 |   };
121 | 
122 |   auto skill_parsed = pre::json::from_json(obj);
123 | 
124 |   BOOST_REQUIRE(skill_parsed.skill_name == "GML");
125 |   BOOST_REQUIRE(skill_parsed.experience == 10);
126 |   std::cout << pre::json::to_json(skill_parsed).dump(2) << std::endl;
127 | }
128 | 
129 | /**
130 |  * Test nested objects
131 |  */
132 | BOOST_AUTO_TEST_CASE (nested) {
133 |   datamodel::customer customer {
134 |     "Mr. Dupond",
135 |     43,
136 |     {1,5},
137 |     {datamodel::skill{"C++", 10}, datamodel::skill{"GML", 20}, datamodel::skill{"Linux", 2}}
138 |   };
139 | 
140 |   datamodel::sales_assitant assistant{"Mr. Gold", 130000, customer};
141 |   auto json_sales_assistant = pre::json::to_json(assistant);
142 |   std::cout << json_sales_assistant.dump(2) << std::endl;
143 | 
144 |   auto deser_assistant = pre::json::from_json(json_sales_assistant);
145 | 
146 |   auto json_sales_assistant_reserialized = pre::json::to_json(deser_assistant);
147 |   std::cout << json_sales_assistant_reserialized.dump(2) << std::endl;
148 | 
149 |   BOOST_REQUIRE(json_sales_assistant_reserialized == json_sales_assistant);
150 | }
151 | 
152 | BOOST_AUTO_TEST_CASE (working_plain_json) {
153 |   std::string json = R"(
154 |     {
155 |         "main_customer": {
156 |             "age": 43,
157 |             "friends_id": [
158 |                 1,
159 |                 5
160 |             ],
161 |             "name": "Mr. Dupond",
162 |             "skillset": [
163 |                 {
164 |                     "experience": 10,
165 |                     "skill_name": "C++"
166 |                 },
167 |                 {
168 |                     "experience": 20,
169 |                     "skill_name": "GML"
170 |                 },
171 |                 {
172 |                     "experience": 2,
173 |                     "skill_name": "Linux"
174 |                 }
175 |             ]
176 |         },
177 |         "nickname": "Mr. Gold",
178 |         "salary": 130000
179 |     }
180 | 
181 |   )";
182 | 
183 |   auto deser_assistant = pre::json::from_json(json);
184 | 
185 |   auto json_sales_assistant_reserialized = pre::json::to_json(deser_assistant);
186 |   std::cout << json_sales_assistant_reserialized.dump(2) << std::endl;
187 | }
188 | 
189 | BOOST_AUTO_TEST_CASE (incorrect_plain_json) {
190 |   // Test buggy keys
191 |   try {
192 |     auto json = R"(
193 |       {
194 |           "main_customer": {
195 |               "BUGGYKEYage": 43,
196 |               "friends_id": [
197 |                   1,
198 |                   5
199 |               ],
200 |               "name": "Mr. Dupond",
201 |               "skillset": [
202 |                   {
203 |                       "experience": 10,
204 |                       "skill_name": "C++"
205 |                   },
206 |                   {
207 |                       "experience": 20,
208 |                       "skill_name": "GML"
209 |                   },
210 |                   {
211 |                       "experience": 2,
212 |                       "skill_name": "Linux"
213 |                   }
214 |               ]
215 |           },
216 |           "nickname": "Mr. Gold",
217 |           "OTHERBUGGYKEYsalary": 130000
218 |       }
219 | 
220 |     )"_json;
221 | 
222 |     auto deser_assistant = pre::json::from_json(json);
223 |     // Must fail
224 |     BOOST_REQUIRE(false);
225 | 
226 |   } catch (...) {
227 |     std::cout << "EXCEPTION which will be outputed to library user : " << std::endl;
228 |     std::cout << boost::current_exception_diagnostic_information(true) << std::endl;
229 |     BOOST_REQUIRE(true);
230 |   }
231 | 
232 |   // Test buggy value types
233 |   try {
234 |     auto json = R"(
235 |       {
236 |           "main_customer": {
237 |               "age": "He is 43 years old, does it fit in an integer ?",
238 |               "friends_id": [
239 |                   1,
240 |                   5
241 |               ],
242 |               "name": "Mr. Dupond",
243 |               "skillset": [
244 |                   {
245 |                       "experience": 10,
246 |                       "skill_name": "C++"
247 |                   },
248 |                   {
249 |                       "experience": 20,
250 |                       "skill_name": "GML"
251 |                   },
252 |                   {
253 |                       "experience": 2,
254 |                       "skill_name": "Linux"
255 |                   }
256 |               ]
257 |           },
258 |           "nickname": "Mr. Gold",
259 |           "salary": 130000
260 |       }
261 | 
262 |     )"_json;
263 | 
264 |     auto deser_assistant = pre::json::from_json(json);
265 |     // Must fail
266 |     BOOST_REQUIRE(false);
267 | 
268 |   } catch (...) {
269 |     std::cout << "EXCEPTION which will be outputed to library user : " << std::endl;
270 |     std::cout << boost::current_exception_diagnostic_information(true) << std::endl;
271 |     BOOST_REQUIRE(true);
272 |   }
273 | }
274 | 
275 | 
276 | BOOST_AUTO_TEST_CASE (containers_direct) {
277 |   std::vector skills {
278 |     datamodel::skill{"C++", 0},
279 |     datamodel::skill{"Java", 0},
280 |     datamodel::skill{".Net", 0},
281 |     datamodel::skill{"Objective-C", 0},
282 |     datamodel::skill{"HTML", 0},
283 |     datamodel::skill{"SQL", 0},
284 |     datamodel::skill{"Project-Management", 0}
285 |   };
286 | 
287 |   auto skills_json = pre::json::to_json(skills);
288 |   std::cout << skills_json.dump(2) << std::endl;
289 | 
290 |   auto skills_deserialized = pre::json::from_json>(skills_json); 
291 |   BOOST_REQUIRE(skills == skills_deserialized);
292 | 
293 |   auto empty_skills = pre::json::to_json( std::vector {} ).dump();
294 |   BOOST_REQUIRE(empty_skills != "null");
295 |   BOOST_REQUIRE(empty_skills == "[]");
296 | 
297 | }
298 | 
299 | namespace datamodel {
300 | 
301 |   struct cleaner {
302 |     std::string floor;
303 |     std::string room;
304 |   };
305 | 
306 | }
307 | 
308 | BOOST_FUSION_ADAPT_STRUCT(datamodel::cleaner,
309 |   floor,
310 |   room)
311 | 
312 | namespace datamodel {
313 | 
314 |   struct cashier {
315 |     std::string section;
316 |     int checkout_number;
317 |   };
318 | 
319 | }
320 | 
321 | BOOST_FUSION_ADAPT_STRUCT(datamodel::cashier,
322 |   section,
323 |   checkout_number)
324 | 
325 | namespace datamodel {
326 | 
327 |   struct security {
328 |     bool has_a_weapon;
329 |     std::string fighting_tactic;
330 |   };
331 | 
332 |   typedef std::variant possible_responsibilities;
333 | }
334 | 
335 | BOOST_FUSION_ADAPT_STRUCT(datamodel::security,
336 |   has_a_weapon,
337 |   fighting_tactic)
338 | 
339 | 
340 | 
341 | namespace datamodel {
342 |   struct employee {
343 |     std::string name;
344 |     possible_responsibilities responsibility;
345 |   };
346 | }
347 | 
348 | BOOST_FUSION_ADAPT_STRUCT(datamodel::employee,
349 |   name,
350 |   responsibility)
351 | 
352 | BOOST_AUTO_TEST_CASE (std_variant) {
353 | 
354 |   std::vector employees {
355 |     {"King", datamodel::cashier{"hardware", 1} },
356 |     {"Blake", datamodel::security{true, "Krav Maga"} },
357 |     {"Martin", datamodel::cleaner{"5th floor", "Toys, Petshop, Drugs, Food" } },
358 |     {"Ward", datamodel::cashier{"Food", 2} }
359 |   };
360 | 
361 |   auto employees_json = pre::json::to_json(employees);
362 |   std::cout << employees_json.dump(2) << std::endl;
363 | 
364 |   auto employees_deserialized = pre::json::from_json>(employees_json); 
365 | 
366 |   auto employees_reserialized = pre::json::to_json(employees_deserialized);
367 |   std::cout << employees_reserialized.dump(2) << std::endl;
368 | 
369 |   BOOST_REQUIRE(employees == employees_deserialized);
370 | }
371 | 
372 | namespace datamodel {
373 | 
374 |   struct struct_with_a_map {
375 |     std::map with_a_map;
376 |     std::map some_other_map;
377 |   };
378 |   
379 | }
380 | 
381 | BOOST_FUSION_ADAPT_STRUCT(datamodel::struct_with_a_map, with_a_map, some_other_map)
382 | 
383 | BOOST_AUTO_TEST_CASE(maps) {
384 | 
385 |   datamodel::struct_with_a_map some{
386 |     {
387 |       {"hellO",12},
388 |       {"help", 15}
389 |     },
390 |     {
391 |       {"test", datamodel::skill{"C++", 10}}
392 |     }
393 |   };
394 | 
395 |   auto some_json = pre::json::to_json(some);
396 |   std::cout << some_json.dump(2) << std::endl; 
397 | 
398 |   auto some_deserialized = pre::json::from_json(some_json);
399 |   
400 |   BOOST_REQUIRE(some_deserialized == some); 
401 | }
402 | 
403 | BOOST_AUTO_TEST_CASE(empty_map) {
404 | 
405 |   std::map some{};
406 | 
407 |   auto some_json = pre::json::to_json(some);
408 |   std::cout << some_json.dump(2) << std::endl; 
409 | 
410 |   auto some_deserialized = pre::json::from_json(some_json);
411 |   
412 |   BOOST_REQUIRE(some_deserialized == some); 
413 | 
414 |   auto empty_map = pre::json::to_json( std::map {} ).dump();
415 |   BOOST_REQUIRE(empty_map != "null");
416 |   BOOST_REQUIRE(empty_map == "{}");
417 | }
418 | 
419 | 
420 | 
421 | 
422 | namespace datamodel {
423 | 
424 |   enum class my_value_type : uint8_t {
425 |     TYPE1,
426 |     TYPE2
427 |   };
428 | 
429 |   enum some_other {
430 |     ONE,
431 |     TWO,
432 |     THREE
433 |   };
434 | 
435 |   struct some_value {
436 |     my_value_type type;
437 |     int value;
438 |     some_other enums_without_underlying;
439 |   };
440 | 
441 | }
442 | 
443 | BOOST_FUSION_ADAPT_STRUCT(datamodel::some_value,
444 |   type,
445 |   value,
446 |   enums_without_underlying)
447 | 
448 | BOOST_AUTO_TEST_CASE (enums) {
449 | 
450 |   datamodel::some_value val{datamodel::my_value_type::TYPE2, 12, datamodel::THREE};
451 | 
452 |   auto val_json = pre::json::to_json(val);
453 |   std::cout << val_json.dump(2) << std::endl;
454 | 
455 |   auto val_deserialized = pre::json::from_json(val_json); 
456 | 
457 |   auto val_reserialized = pre::json::to_json(val_deserialized);
458 |   std::cout << val_reserialized.dump(2) << std::endl;
459 | 
460 |   BOOST_REQUIRE(val == val_deserialized);
461 | }
462 | 
463 | BOOST_AUTO_TEST_CASE (adapted_struct_jsonize_chrono) {
464 | 
465 |   std::chrono::milliseconds val{100};
466 | 
467 |   auto val_json = pre::json::to_json(val);
468 |   std::cout << val_json.dump(2) << std::endl;
469 | 
470 |   auto val_deserialized = pre::json::from_json(val_json); 
471 | 
472 |   auto val_reserialized = pre::json::to_json(val_deserialized);
473 |   std::cout << val_reserialized.dump(2) << std::endl;
474 | 
475 |   BOOST_REQUIRE(val == val_deserialized);
476 | }
477 | 
478 | namespace datamodel {
479 |   struct some_time {
480 |     std::string label;
481 |     std::chrono::milliseconds millis;
482 |     std::chrono::minutes mins;
483 |   };
484 | 
485 | }
486 | 
487 | BOOST_FUSION_ADAPT_STRUCT(datamodel::some_time,
488 |   label,
489 |   millis,
490 |   mins)
491 | 
492 | BOOST_AUTO_TEST_CASE (adapted_struct_jsonize_chrono_composed) {
493 | 
494 |   datamodel::some_time val{"my time", std::chrono::milliseconds(100), std::chrono::minutes(43)};
495 | 
496 |   auto val_json = pre::json::to_json(val);
497 |   std::cout << val_json.dump(2) << std::endl;
498 | 
499 |   auto val_deserialized = pre::json::from_json(val_json); 
500 | 
501 |   auto val_reserialized = pre::json::to_json(val_deserialized);
502 |   std::cout << val_reserialized.dump(2) << std::endl;
503 | 
504 |   BOOST_REQUIRE(val == val_deserialized);
505 | }
506 | 
507 | namespace datamodel {
508 |   struct with_optional_member {
509 |     std::optional field_optional; 
510 |     double other; 
511 |   };
512 | }
513 | 
514 | BOOST_FUSION_ADAPT_STRUCT(datamodel::with_optional_member,
515 |   field_optional,
516 |   other)
517 | 
518 | BOOST_AUTO_TEST_CASE (optional) {
519 | 
520 |   std::optional val{"some text"};
521 | 
522 |   auto val_json = pre::json::to_json(val);
523 |   std::cout << val_json.dump(2) << std::endl;
524 | 
525 |   auto val_deserialized = pre::json::from_json>(val_json); 
526 | 
527 |   auto val_reserialized = pre::json::to_json(val_deserialized);
528 |   std::cout << val_reserialized.dump(2) << std::endl;
529 | 
530 |   BOOST_REQUIRE(val == val_deserialized);
531 | }
532 | 
533 | BOOST_AUTO_TEST_CASE (optional_member) {
534 | 
535 |   {
536 |     datamodel::with_optional_member val;
537 |     val.field_optional = 12.32;
538 |     val.other = 13.21;
539 | 
540 |     auto val_json = pre::json::to_json(val);
541 |     std::cout << val_json.dump(2) << std::endl;
542 | 
543 |     auto val_deserialized = pre::json::from_json(val_json); 
544 | 
545 |     auto val_reserialized = pre::json::to_json(val_deserialized);
546 |     std::cout << val_reserialized.dump(2) << std::endl;
547 | 
548 |     BOOST_REQUIRE(val == val_deserialized);
549 |   }
550 | 
551 |   {
552 |     datamodel::with_optional_member val;
553 |     val.other = 43.21;
554 | 
555 |     auto val_json = pre::json::to_json(val);
556 |     std::cout << val_json.dump(2) << std::endl;
557 | 
558 |     auto val_deserialized = pre::json::from_json(val_json); 
559 | 
560 |     auto val_reserialized = pre::json::to_json(val_deserialized);
561 |     std::cout << val_reserialized.dump(2) << std::endl;
562 | 
563 |     BOOST_REQUIRE(val == val_deserialized);
564 |   }
565 | }
566 | 
567 | 
568 | namespace datamodel {
569 |   typedef std::variant possible_responsibilities_std;
570 | 
571 |   struct with_std_variant{
572 |     possible_responsibilities_std responsibility;
573 |     std::optional additional_responsibility;
574 |   };
575 | }
576 | 
577 | BOOST_FUSION_ADAPT_STRUCT(datamodel::with_std_variant,
578 |   responsibility,
579 |   additional_responsibility)
580 | 
581 | 
582 | BOOST_AUTO_TEST_CASE (std_variant_simple) {
583 | 
584 |   {
585 |     using datamodel::with_std_variant;
586 |     using datamodel::possible_responsibilities_std;
587 |     using datamodel::cashier;
588 |     using datamodel::cleaner;
589 |     using datamodel::security;
590 | 
591 |     with_std_variant val{cashier{"hardware", 1} } ;
592 | 
593 |     auto val_json = pre::json::to_json(val);
594 |     std::cout << val_json.dump(2) << std::endl;
595 | 
596 |     auto val_deserialized = pre::json::from_json(val_json); 
597 | 
598 |     auto val_reserialized = pre::json::to_json(val_deserialized);
599 |     std::cout << val_reserialized.dump(2) << std::endl;
600 | 
601 |     BOOST_REQUIRE(val == val_deserialized);
602 |   }
603 | 
604 | 
605 | }
606 | 
607 | 
608 | BOOST_AUTO_TEST_CASE (std_variant_complex) {
609 | 
610 |   {
611 |     using datamodel::with_std_variant;
612 |     using datamodel::possible_responsibilities_std;
613 |     using datamodel::cashier;
614 |     using datamodel::cleaner;
615 |     using datamodel::security;
616 | 
617 |     std::vector val {
618 |       with_std_variant{cashier{"hardware", 1} },
619 |       with_std_variant{security{true, "Krav Maga"}, possible_responsibilities_std{cleaner{"Entrance", "Doors" }}},
620 |       with_std_variant{cleaner{"5th floor", "Toys, Petshop, Drugs, Food" } },
621 |       with_std_variant{cashier{"Food", 2} }
622 |     };
623 | 
624 |     auto val_json = pre::json::to_json(val);
625 |     std::cout << val_json.dump(2) << std::endl;
626 | 
627 |     auto val_deserialized = pre::json::from_json(val_json); 
628 | 
629 |     auto val_reserialized = pre::json::to_json(val_deserialized);
630 |     std::cout << val_reserialized.dump(2) << std::endl;
631 | 
632 |     BOOST_REQUIRE(val == val_deserialized);
633 |   }
634 | 
635 | 
636 | }
637 | 


--------------------------------------------------------------------------------
/test/variant_for_each_type.cpp:
--------------------------------------------------------------------------------
 1 | #define BOOST_TEST_MODULE for_each_type
 2 | #include 
 3 | 
 4 | #include "wasm_boost_test.hpp"
 5 | 
 6 | #include 
 7 | #include 
 8 | #include 
 9 | 
10 | /* Goal is to test compilation with temporary visitor and with non copyable ones. */
11 | 
12 | using std_test_variant = std::variant;
13 | 
14 | struct uncopyable_visitor {
15 |   uncopyable_visitor() = default;
16 |   ~uncopyable_visitor() = default;
17 |   uncopyable_visitor(const uncopyable_visitor&) = delete; 
18 | 
19 |   template
20 |   void operator()(const T&) { std::cout << typeid(T).name() << std::endl; }
21 | };
22 | 
23 | BOOST_AUTO_TEST_CASE (std_test) {
24 | 
25 |     uncopyable_visitor each{};
26 |     pre::variant::for_each_type(std_test_variant{}, each);
27 |     pre::variant::for_each_type(std_test_variant{}, uncopyable_visitor{});
28 | }
29 | 


--------------------------------------------------------------------------------
/test/wasm_boost_test.hpp:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | 
 4 | #ifdef __EMSCRIPTEN__
 5 | 	#include 
 6 | 	extern "C" {
 7 | 		int sigaltstack(const stack_t *__restrict, stack_t *__restrict) { return 0; } //XXX: Check in newer emcc version if we can remove this.
 8 | 	}
 9 | #endif
10 | 


--------------------------------------------------------------------------------