#pragma once #include "library/cpp/json/writer/json_value.h" #include #include #include #include #include #include #include namespace NJson { template struct TConverter { }; namespace { template struct TDefaultEncoder { static inline TJsonValue Encode(T value) { return TJsonValue(value); } }; template struct TDefaultArrayEncoder { static TJsonValue Encode(const T& value) { TJsonValue result(NJson::JSON_ARRAY); auto& encodedArray = result.GetArraySafe(); for (const auto& element : value) { encodedArray.push_back(TConverter::Encode(element)); } return result; } }; template struct TDefaultArrayDecoder { static T Decode(const TJsonValue& value) { T result; for (const auto& element : value.GetArraySafe()) { result.push_back(TConverter::Decode(element)); } return result; } }; template struct TDefaultArrayConverter: public TDefaultArrayEncoder, public TDefaultArrayDecoder { }; template struct TDefaultMapEncoder { static TJsonValue Encode(const T& value) { TJsonValue result(NJson::JSON_MAP); auto& encodedMap = result.GetMapSafe(); for (const auto& [key, element] : value) { encodedMap[key] = TConverter::Encode(element); } return result; } }; template struct TDefaultMapDecoder { static T Decode(const TJsonValue& value) { T result; for (const auto& [key, element] : value.GetMapSafe()) { result[key] = TConverter::Decode(element); } return result; } }; template struct TDefaultMapConverter: public TDefaultMapEncoder, public TDefaultMapDecoder { }; } template<> struct TConverter { static TJsonValue Encode(const TJsonValue& value) { return value; } static TJsonValue Decode(const TJsonValue& value) { return value; } }; template<> struct TConverter: public TDefaultEncoder { static inline bool Decode(const TJsonValue& value) { return value.GetBooleanSafe(); } }; template requires std::is_integral_v && (!std::is_same_v) struct TConverter: public TDefaultEncoder { static T Decode(const TJsonValue& value) { if constexpr (std::is_signed_v) { const auto decodedValue = value.GetIntegerSafe(); if (decodedValue < std::numeric_limits::min() || std::numeric_limits::max() < decodedValue) { ythrow yexception() << "Out of range (got " << decodedValue << ")"; } return static_cast(decodedValue); } else { const auto decodedValue = value.GetUIntegerSafe(); if (std::numeric_limits::max() < decodedValue) { ythrow yexception() << "Out of range (got " << decodedValue << ")"; } return static_cast(decodedValue); } } }; template requires std::is_floating_point_v struct TConverter: public TDefaultEncoder { static inline T Decode(const TJsonValue& value) { return static_cast(value.GetDoubleSafe()); } }; template<> struct TConverter: public TDefaultEncoder { }; template<> struct TConverter: public TDefaultEncoder { static inline TString Decode(const TJsonValue& value) { return value.GetStringSafe(); } }; template struct TConverter> { static TJsonValue Encode(const TMaybe& value) { if (value.Defined()) { return TConverter::Encode(*value); } else { return TJsonValue(NJson::JSON_NULL); } } static TMaybe Decode(const TJsonValue& value) { if (value.IsDefined()) { return TConverter::Decode(value); } else { return Nothing(); } } }; template struct TConverter>: public TDefaultArrayEncoder, T> { }; template struct TConverter>: public TDefaultArrayConverter, T> { }; template struct TConverter>: public TDefaultArrayConverter, T> { }; template struct TConverter>: public TDefaultArrayConverter, T> { }; template struct TConverter>: public TDefaultMapEncoder, T> { }; template struct TConverter>: public TDefaultMapConverter, T> { }; template struct TConverter>: public TDefaultMapEncoder, T> { }; template struct TConverter>: public TDefaultMapConverter, T> { }; }