C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
json_extensions.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include "char8_t_remediation.hpp"
26#include "error_extensions.hpp"
27#include "exception.hpp"
28#include "json_compat.hpp"
29#include "meta/naming_convention.hpp"
30#include "reflection.hpp"
31
32#include <cstddef>
33#include <cstdint>
34#include <filesystem>
35#include <fstream>
36#include <string>
37#include <string_view>
38#include <type_traits>
39#include <utility>
40
41namespace essence {
42 template <typename Visitor>
43 decltype(auto) visit_json(const json& value, Visitor&& visitor) {
44 using nlohmann::detail::value_t;
45
46 switch (value.type()) {
47 case value_t::null:
48 return std::forward<Visitor>(visitor)(nullptr);
49 case value_t::object:
50 return std::forward<Visitor>(visitor)(value);
51 case value_t::array:
52 return std::forward<Visitor>(visitor)(value.get<json::array_t>());
53 case value_t::boolean:
54 return std::forward<Visitor>(visitor)(value.get<bool>());
55 case value_t::string:
56 return std::forward<Visitor>(visitor)(value.get<std::string>());
57 case value_t::number_float:
58 return std::forward<Visitor>(visitor)(value.get<double>());
59 case value_t::number_integer:
60 return std::forward<Visitor>(visitor)(value.get<std::int64_t>());
61 case value_t::number_unsigned:
62 return std::forward<Visitor>(visitor)(value.get<std::uint64_t>());
63 default:
64 return std::forward<Visitor>(visitor)(value);
65 }
66 }
67} // namespace essence
68
69namespace essence {
70 template <meta::reflectable T, meta::naming_convention Convention>
72 using fields_t = meta::get_fields_t<T>;
73
74 static void from_json(const json& value, T& obj) {
75 for_each_as_values<fields_t>([&]<typename... Ts>(std::type_identity<Ts>...) {
76 // Creates a json null value if not exist, as a std::optional<T> may need this value.
77 (value.value(meta::convert_naming_convention(Ts::name, Convention), json{}).get_to(Ts::value_ref(obj)),
78 ...);
79 });
80 }
81
82 static void to_json(json& value, const T& obj) {
83 for_each_as_values<fields_t>([&]<typename... Ts>(std::type_identity<Ts>...) {
84 auto handler = [&]<typename U>(std::type_identity<U>) {
85 if (json intermediate(U::value_ref(obj)); !intermediate.is_null()) {
86 value.emplace(meta::convert_naming_convention(U::name, Convention), std::move(intermediate));
87 }
88 };
89
90 (handler(std::type_identity<Ts>{}), ...);
91 });
92 }
93 };
94
95 template <json_serializable T>
96 T deserialize_json(const std::filesystem::path& path) {
97 return throw_nested_and_flatten(
98 source_code_aware_runtime_error{U8("Deserialization Failed"), from_u8string(path.u8string())}, [&] {
99 std::ifstream stream{path, std::ios::binary};
100
101 stream.exceptions(std::ifstream::failbit);
102
103 return json::parse(stream).get<T>();
104 });
105 }
106} // namespace essence
107
108#define ES_JSON_SERIALIZABLE(naming_convention) \
109 friend void from_json(const essence::json& value, es_meta_this_type& obj) { \
110 essence::json_serializer<es_meta_this_type, naming_convention>::from_json(value, obj); \
111 } \
112 \
113 friend void to_json(essence::json& value, const es_meta_this_type& obj) { \
114 essence::json_serializer<es_meta_this_type, naming_convention>::to_json(value, obj); \
115 } \
116 \
117 ES_MAKE_TERMINATOR(__COUNTER__)
118
119#define ES_JSON_SERIALIZABLE_DEFAULT ES_JSON_SERIALIZABLE(essence::meta::naming_convention::camel)
namespace for Niels Lohmann
Definition json.hpp:19415
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:19657
@ value
the parser finished reading a JSON value
Definition json_extensions.hpp:71
An exception class derived from std::runtime_error that provides source code information of the sourc...
Definition error_extensions.hpp:73