3#include <nlohmann/json.hpp>
16namespace TgBot::Json {
19void decode(
const nlohmann::json& json, T& value);
22void decode(
const nlohmann::json& json, std::shared_ptr<T>& value);
25void decode(
const nlohmann::json& json, std::optional<T>& value);
28void decode(
const nlohmann::json& json, std::vector<T>& value);
30template<std::size_t Index = 0,
typename... T>
31void decode(
const nlohmann::json& json, std::variant<T...>& value);
34bool matchesDiscriminator(
const nlohmann::json& json) {
35 if constexpr (
requires {
typename T::element_type; }) {
36 using Element =
typename T::element_type;
37 if constexpr (
requires { Element::TYPE; }) {
38 return json.is_object() && json.value(
"type", std::string { }) == Element::TYPE;
40 if constexpr (
requires { Element::STATUS; }) {
41 return json.is_object() && json.value(
"status", std::string { }) == Element::STATUS;
43 if constexpr (
requires { Element::SOURCE; }) {
44 return json.is_object() && json.value(
"source", std::string { }) == Element::SOURCE;
52void decode(
const nlohmann::json& json, T& value) {
57void decode(
const nlohmann::json& json, std::shared_ptr<T>& value) {
59 throw std::invalid_argument(
"Required Telegram object is null");
61 value = std::make_shared<T>();
66void decode(
const nlohmann::json& json, std::optional<T>& value) {
76void decode(
const nlohmann::json& json, std::vector<T>& value) {
77 if (!json.is_array()) {
78 throw std::invalid_argument(
"Telegram array field is not an array");
81 value.reserve(json.size());
82 for (
const auto& item : json) {
84 decode(item, decoded);
85 value.push_back(std::move(decoded));
89template<std::size_t Index,
typename... T>
90void decode(
const nlohmann::json& json, std::variant<T...>& value) {
91 if constexpr (Index ==
sizeof...(T)) {
92 throw std::invalid_argument(
"JSON value does not match Telegram union");
95 using Candidate = std::variant_alternative_t<Index, std::variant<T...>>;
96 if (!matchesDiscriminator<Candidate>(json)) {
97 throw std::invalid_argument(
"Telegram union discriminator does not match");
99 Candidate candidate { };
100 decode(json, candidate);
101 value = std::move(candidate);
102 }
catch (
const std::exception&) {
103 decode<Index + 1>(json, value);
109nlohmann::json encode(
const T& value);
112nlohmann::json encode(
const std::shared_ptr<T>& value);
115nlohmann::json encode(
const std::optional<T>& value);
118nlohmann::json encode(
const std::vector<T>& value);
120template<
typename... T>
121nlohmann::json encode(
const std::variant<T...>& value);
124nlohmann::json encode(
const T& value) {
125 return nlohmann::json(value);
129nlohmann::json encode(
const std::shared_ptr<T>& value) {
140nlohmann::json encode(
const std::optional<T>& value) {
141 return value ? encode(*value) : nlohmann::json(nullptr);
145nlohmann::json encode(
const std::vector<T>& value) {
146 nlohmann::json json = nlohmann::json::array();
147 for (
const auto& item : value) {
148 json.push_back(encode(item));
154template<
typename... T>
155nlohmann::json encode(
const std::variant<T...>& value) {
157 [](
const auto& item) {
164void readRequiredField(
const nlohmann::json& json,
const char* name, T& value) {
165 decode(json.at(name), value);
169void readOptionalField(
const nlohmann::json& json,
const char* name, T& value) {
170 const auto item = json.find(name);
171 if (item == json.end() || item->is_null()) {
175 decode(*item, value);
179void writeRequiredField(nlohmann::json& json,
const char* name,
const T& value) {
180 json[name] = encode(value);
184void writeOptionalField(nlohmann::json& json,
const char* name,
const std::optional<T>& value) {
186 json[name] = encode(value);
191void writeOptionalField(nlohmann::json& json,
const char* name,
const std::shared_ptr<T>& value) {
193 json[name] = encode(value);
TGBOT_API void to_json(nlohmann::json &json, const AcceptedGiftTypes &value)
TGBOT_API void from_json(const nlohmann::json &json, AcceptedGiftTypes &value)