forgeant docs-test-0
Build LLM-powered agents in C++
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1#ifndef FORGEANT_JSON_JSON_HPP
2#define FORGEANT_JSON_JSON_HPP
3
4#include <cstdint>
5#include <initializer_list>
6#include <map>
7#include <stdexcept>
8#include <string>
9#include <string_view>
10#include <type_traits>
11#include <utility>
12#include <variant>
13#include <vector>
14
15namespace forgeant {
16
17namespace detail {
18
19template <typename T>
20struct IsVector : std::false_type {};
21
22template <typename T, typename A>
23struct IsVector<std::vector<T, A>> : std::true_type {};
24
25} // namespace detail
26
27class Json {
28 public:
29 using null_t = std::nullptr_t;
30 using boolean_t = bool;
31 using integer_t = std::int64_t;
32 using number_t = double;
33 using string_t = std::string;
34 using array_t = std::vector<Json>;
35 using object_t = std::map<std::string, Json>;
36
37 Json() : value_(nullptr) {}
38 Json(std::nullptr_t) : value_(nullptr) {}
39
40 template <typename T>
41 requires std::same_as<T, bool>
42 Json(T b) : value_(boolean_t{b}) {}
43
44 template <typename T>
45 requires(std::integral<T> && !std::same_as<T, bool>)
46 Json(T n) : value_(static_cast<integer_t>(n)) {}
47
48 template <typename T>
49 requires std::floating_point<T>
50 Json(T d) : value_(static_cast<number_t>(d)) {}
51
52 Json(const char* s) : value_(string_t(s)) {}
53 Json(std::string_view sv) : value_(string_t(sv)) {}
54 Json(string_t s) : value_(std::move(s)) {}
55 Json(array_t arr) : value_(std::move(arr)) {}
56 Json(object_t obj) : value_(std::move(obj)) {}
57
58 Json(const Json&) = default;
59 Json(Json&&) noexcept = default;
60 Json& operator=(const Json&) = default;
61 Json& operator=(Json&&) noexcept = default;
62 ~Json() = default;
63
64 [[nodiscard]] bool is_null() const { return std::holds_alternative<null_t>(value_); }
65 [[nodiscard]] bool is_boolean() const { return std::holds_alternative<boolean_t>(value_); }
66
67 [[nodiscard]] bool is_number() const {
68 return std::holds_alternative<integer_t>(value_) ||
69 std::holds_alternative<number_t>(value_);
70 }
71
72 [[nodiscard]] bool is_string() const { return std::holds_alternative<string_t>(value_); }
73 [[nodiscard]] bool is_array() const { return std::holds_alternative<array_t>(value_); }
74 [[nodiscard]] bool is_object() const { return std::holds_alternative<object_t>(value_); }
75
76 Json& operator[](const std::string& key) {
77 if (is_null()) {
78 value_ = object_t{};
79 }
80 return std::get<object_t>(value_)[key];
81 }
82
83 const Json& operator[](const std::string& key) const {
84 return std::get<object_t>(value_).at(key);
85 }
86
87 Json& operator[](std::size_t index) { return std::get<array_t>(value_)[index]; }
88
89 const Json& operator[](std::size_t index) const { return std::get<array_t>(value_)[index]; }
90
91 Json& at(const std::string& key) {
92 if (!is_object()) {
93 throw std::out_of_range("Json::at: not an object");
94 }
95 auto& obj = std::get<object_t>(value_);
96 auto it = obj.find(key);
97 if (it == obj.end()) {
98 throw std::out_of_range("Json::at: key not found: " + key);
99 }
100 return it->second;
101 }
102
103 [[nodiscard]] const Json& at(const std::string& key) const {
104 if (!is_object()) {
105 throw std::out_of_range("Json::at: not an object");
106 }
107 const auto& obj = std::get<object_t>(value_);
108 auto it = obj.find(key);
109 if (it == obj.end()) {
110 throw std::out_of_range("Json::at: key not found: " + key);
111 }
112 return it->second;
113 }
114
115 template <typename T>
116 [[nodiscard]] T value(const std::string& key, const T& default_value) const {
117 if (!is_object()) {
118 return default_value;
119 }
120 const auto& obj = std::get<object_t>(value_);
121 auto it = obj.find(key);
122 if (it == obj.end()) {
123 return default_value;
124 }
125 return it->second.get<T>();
126 }
127
128 [[nodiscard]] std::string value(const std::string& key, const char* default_value) const {
129 return value<std::string>(key, std::string(default_value));
130 }
131
132 [[nodiscard]] bool contains(const std::string& key) const {
133 if (!is_object()) {
134 return false;
135 }
136 return std::get<object_t>(value_).contains(key);
137 }
138
139 void push_back(Json val) {
140 if (is_null()) {
141 value_ = array_t{};
142 }
143 std::get<array_t>(value_).push_back(std::move(val));
144 }
145
146 [[nodiscard]] bool empty() const {
147 if (is_array()) {
148 return std::get<array_t>(value_).empty();
149 }
150 if (is_object()) {
151 return std::get<object_t>(value_).empty();
152 }
153 if (is_null()) {
154 return true;
155 }
156 return false;
157 }
158
159 [[nodiscard]] std::size_t size() const {
160 if (is_array()) {
161 return std::get<array_t>(value_).size();
162 }
163 if (is_object()) {
164 return std::get<object_t>(value_).size();
165 }
166 return 0;
167 }
168
169 using iterator = array_t::iterator;
170 using const_iterator = array_t::const_iterator;
171
172 [[nodiscard]] iterator begin() { return std::get<array_t>(value_).begin(); }
173 [[nodiscard]] iterator end() { return std::get<array_t>(value_).end(); }
174 [[nodiscard]] const_iterator begin() const { return std::get<array_t>(value_).begin(); }
175 [[nodiscard]] const_iterator end() const { return std::get<array_t>(value_).end(); }
176
177 template <typename T>
178 [[nodiscard]] T get() const {
179 using U = std::remove_cvref_t<T>;
180 if constexpr (std::is_same_v<U, Json>) {
181 return *this;
182 } else if constexpr (std::is_same_v<U, string_t>) {
183 return std::get<string_t>(value_);
184 } else if constexpr (std::is_same_v<U, bool>) {
185 return std::get<boolean_t>(value_);
186 } else if constexpr (std::is_same_v<U, integer_t>) {
187 return std::get<integer_t>(value_);
188 } else if constexpr (std::is_integral_v<U> && !std::is_same_v<U, bool>) {
189 return static_cast<U>(std::get<integer_t>(value_));
190 } else if constexpr (std::is_floating_point_v<U>) {
191 if (std::holds_alternative<integer_t>(value_)) {
192 return static_cast<U>(std::get<integer_t>(value_));
193 }
194 return static_cast<U>(std::get<number_t>(value_));
195 } else if constexpr (detail::IsVector<U>::value) {
196 using elem_t = typename U::value_type;
197 const auto& arr = std::get<array_t>(value_);
198 U result;
199 result.reserve(arr.size());
200 for (const auto& elem : arr) {
201 result.push_back(elem.get<elem_t>());
202 }
203 return result;
204 } else {
205 U result{};
206 from_json(*this, result);
207 return result;
208 }
209 }
210
211 template <typename T>
212 void get_to(T& val) const {
213 val = get<T>();
214 }
215
216 [[nodiscard]] bool operator==(const Json& other) const { return value_ == other.value_; }
217
218 [[nodiscard]] std::string dump() const;
219 static Json parse(std::string_view input);
220
221 static Json array() { return {array_t{}}; }
222
223 static Json array(std::initializer_list<Json> init) {
224 array_t arr;
225 arr.reserve(init.size());
226 for (const auto& elem : init) {
227 arr.push_back(elem);
228 }
229 return {std::move(arr)};
230 }
231 static Json object() { return {object_t{}}; }
232
233 static Json object(std::initializer_list<std::pair<const std::string, Json>> init) {
234 object_t obj;
235 for (const auto& [key, val] : init) {
236 obj.emplace(key, val);
237 }
238 return {std::move(obj)};
239 }
240
241 private:
242 void write_to(std::string& out) const;
243
244 std::variant<null_t, boolean_t, integer_t, number_t, string_t, array_t, object_t> value_;
245};
246
247namespace json {
248
249Json parse(std::string_view input);
250std::string dump(const Json& j);
251Json array();
252Json object();
253
254} // namespace json
255
256} // namespace forgeant
257
258#endif // FORGEANT_JSON_JSON_HPP
Definition json.hpp:27
bool operator==(const Json &other) const
Definition json.hpp:216
const Json & operator[](const std::string &key) const
Definition json.hpp:83
static Json parse(std::string_view input)
Json & at(const std::string &key)
Definition json.hpp:91
bool is_string() const
Definition json.hpp:72
Json(T b)
Definition json.hpp:42
std::int64_t integer_t
Definition json.hpp:31
std::size_t size() const
Definition json.hpp:159
array_t::iterator iterator
Definition json.hpp:169
Json(const char *s)
Definition json.hpp:52
const Json & operator[](std::size_t index) const
Definition json.hpp:89
Json(T d)
Definition json.hpp:50
static Json object()
Definition json.hpp:231
static Json array()
Definition json.hpp:221
T get() const
Definition json.hpp:178
Json(T n)
Definition json.hpp:46
Json(Json &&) noexcept=default
array_t::const_iterator const_iterator
Definition json.hpp:170
iterator end()
Definition json.hpp:173
iterator begin()
Definition json.hpp:172
bool is_number() const
Definition json.hpp:67
std::string dump() const
static Json object(std::initializer_list< std::pair< const std::string, Json > > init)
Definition json.hpp:233
bool is_null() const
Definition json.hpp:64
Json(array_t arr)
Definition json.hpp:55
T value(const std::string &key, const T &default_value) const
Definition json.hpp:116
const Json & at(const std::string &key) const
Definition json.hpp:103
bool is_array() const
Definition json.hpp:73
Json(std::nullptr_t)
Definition json.hpp:38
std::vector< Json > array_t
Definition json.hpp:34
bool is_boolean() const
Definition json.hpp:65
Json(object_t obj)
Definition json.hpp:56
const_iterator begin() const
Definition json.hpp:174
std::nullptr_t null_t
Definition json.hpp:29
double number_t
Definition json.hpp:32
std::string value(const std::string &key, const char *default_value) const
Definition json.hpp:128
void get_to(T &val) const
Definition json.hpp:212
bool contains(const std::string &key) const
Definition json.hpp:132
Json(const Json &)=default
bool empty() const
Definition json.hpp:146
const_iterator end() const
Definition json.hpp:175
void push_back(Json val)
Definition json.hpp:139
Json & operator[](const std::string &key)
Definition json.hpp:76
std::string string_t
Definition json.hpp:33
static Json array(std::initializer_list< Json > init)
Definition json.hpp:223
bool is_object() const
Definition json.hpp:74
Json & operator[](std::size_t index)
Definition json.hpp:87
Json()
Definition json.hpp:37
std::map< std::string, Json > object_t
Definition json.hpp:35
Json(string_t s)
Definition json.hpp:54
Json(std::string_view sv)
Definition json.hpp:53
bool boolean_t
Definition json.hpp:30
Definition agent.hpp:25
void from_json(const Json &j, TextBlock &block)
Definition json.hpp:20