37 Json() : value_(nullptr) {}
38 Json(std::nullptr_t) : value_(nullptr) {}
41 requires std::same_as<T, bool>
45 requires(std::integral<T> && !std::same_as<T, bool>)
49 requires std::floating_point<T>
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_); }
68 return std::holds_alternative<integer_t>(value_) ||
69 std::holds_alternative<number_t>(value_);
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_); }
80 return std::get<object_t>(value_)[key];
84 return std::get<object_t>(value_).
at(key);
87 Json&
operator[](std::size_t index) {
return std::get<array_t>(value_)[index]; }
89 const Json&
operator[](std::size_t index)
const {
return std::get<array_t>(value_)[index]; }
93 throw std::out_of_range(
"Json::at: not an object");
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);
103 [[nodiscard]]
const Json&
at(
const std::string& key)
const {
105 throw std::out_of_range(
"Json::at: not an object");
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);
115 template <
typename T>
116 [[nodiscard]] T
value(
const std::string& key,
const T& default_value)
const {
118 return default_value;
120 const auto& obj = std::get<object_t>(value_);
121 auto it = obj.find(key);
122 if (it == obj.end()) {
123 return default_value;
125 return it->second.get<T>();
128 [[nodiscard]] std::string
value(
const std::string& key,
const char* default_value)
const {
129 return value<std::string>(key, std::string(default_value));
132 [[nodiscard]]
bool contains(
const std::string& key)
const {
136 return std::get<object_t>(value_).contains(key);
143 std::get<array_t>(value_).push_back(std::move(val));
148 return std::get<array_t>(value_).empty();
151 return std::get<object_t>(value_).empty();
159 [[nodiscard]] std::size_t
size()
const {
161 return std::get<array_t>(value_).size();
164 return std::get<object_t>(value_).size();
172 [[nodiscard]]
iterator begin() {
return std::get<array_t>(value_).begin(); }
173 [[nodiscard]]
iterator end() {
return std::get<array_t>(value_).end(); }
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>) {
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_));
194 return static_cast<U
>(std::get<number_t>(value_));
196 using elem_t =
typename U::value_type;
197 const auto& arr = std::get<array_t>(value_);
199 result.reserve(arr.size());
200 for (
const auto& elem : arr) {
201 result.push_back(elem.get<elem_t>());
211 template <
typename T>
216 [[nodiscard]]
bool operator==(
const Json& other)
const {
return value_ == other.value_; }
218 [[nodiscard]] std::string
dump()
const;
225 arr.reserve(init.size());
226 for (
const auto& elem : init) {
229 return {std::move(arr)};
233 static Json object(std::initializer_list<std::pair<const std::string, Json>> init) {
235 for (
const auto& [key, val] : init) {
236 obj.emplace(key, val);
238 return {std::move(obj)};
242 void write_to(std::string& out)
const;
244 std::variant<null_t, boolean_t, integer_t, number_t, string_t, array_t, object_t> value_;