#pragma once #include #include #include #include #include #include #include #include "scheme.h" namespace NJsonConverters { class IJsonSerializable { public: virtual NSc::TValue ToTValue() const = 0; virtual void FromTValue(const NSc::TValue&, const bool validate) = 0; const TString ToJson(const bool sort = false) const { return ToTValue().ToJson(sort); } void FromJson(const TStringBuf& json, const bool validate = false) { NSc::TValue v = NSc::TValue::FromJson(json); FromTValue(v, validate); } virtual ~IJsonSerializable() = default; }; ////////////////////////////////////////////////////////////////////// // fwd declarations ////////////////////////////////////////////////////////////////////// //TVector template NSc::TValue ToTValue(const TVector& x); template void FromTValue(const NSc::TValue& x, TVector& out, const bool validate); //THashMap template NSc::TValue ToTValue(const THashMap& x); template void FromTValue(const NSc::TValue& x, THashMap& out, const bool validate); //TMap template NSc::TValue ToTValue(const TMap& x); template void FromTValue(const NSc::TValue& x, TMap& out, const bool validate); //THashSet template NSc::TValue ToTValue(const THashSet& x); template void FromTValue(const NSc::TValue& x, THashSet& out, const bool validate); //TSet template NSc::TValue ToTValue(const TSet& x); template void FromTValue(const NSc::TValue& x, TSet& out, const bool validate); //std::pair template NSc::TValue ToTValue(const std::pair& x); template void FromTValue(const NSc::TValue& x, std::pair& out, const bool validate); ////////////////////////////////////////////////////////////////////// // simple From, To helpers ////////////////////////////////////////////////////////////////////// template struct TValueAndStrokaConv {}; template struct TValueAndStrokaConv { static NSc::TValue ToTValue(const T& x) { return NSc::TValue(x); } static void FromTValue(const NSc::TValue& x, T& out, const bool) { out = x; } static TString ToString(const T& x) { return ::ToString(x); } static void FromString(const TStringBuf& str, T& res, const bool) { res = ::FromString(str); } }; template struct TValueAndStrokaConv { static NSc::TValue ToTValue(const T& x) { return x.ToTValue(); } static void FromTValue(const NSc::TValue& x, T& out, const bool validate) { out.FromTValue(x, validate); } static TString ToString(const T& x) { return x.ToJson(); } static void FromString(const TStringBuf& str, T& res, const bool validate) { res.FromJson(str, validate); } }; template NSc::TValue ToTValue(const T& x) { return TValueAndStrokaConv::value>::ToTValue(x); } template void FromTValue(const NSc::TValue& x, T& out, const bool validate) { return TValueAndStrokaConv::value>::FromTValue(x, out, validate); } template T FromTValue(const NSc::TValue& x, const bool validate) { T ret; FromTValue(x, ret, validate); return ret; } template TString ToString(const T& x) { return TValueAndStrokaConv::value>::ToString(x); } template void FromString(const TStringBuf& str, T& res, const bool validate) { return TValueAndStrokaConv::value>::FromString(str, res, validate); } template T FromString(const TStringBuf& str, bool validate) { T ret; FromString(str, ret, validate); return ret; } namespace NPrivate { template NSc::TValue ToTValueDict(const T& dict) { NSc::TValue out; out.SetDict(); for (typename T::const_iterator it = dict.begin(); it != dict.end(); ++it) { out[ToString(it->first)] = NJsonConverters::ToTValue(it->second); } return out; } template void FromTValueDict(const NSc::TValue& x, T& out, bool validate) { typedef typename T::key_type TKey; typedef typename T::mapped_type TMapped; if (validate) Y_ENSURE(x.IsDict() || x.IsNull(), "not valid input scheme"); out.clear(); if (x.IsDict()) { const NSc::TDict& dict = x.GetDict(); for (const auto& it : dict) { TKey key = NJsonConverters::FromString(it.first, validate); TMapped val = NJsonConverters::FromTValue(it.second, validate); out.insert(std::pair(key, val)); } } } template NSc::TValue ToTValueSet(const T& set) { NSc::TValue out; out.SetDict(); for (typename T::const_iterator it = set.begin(); it != set.end(); ++it) { out[ToString(*it)] = NSc::Null(); } return out; } template void FromTValueSet(const NSc::TValue& x, T& out, const bool validate) { typedef typename T::key_type TKey; if (validate) Y_ENSURE(x.IsDict() || x.IsNull(), "not valid input scheme"); out.clear(); if (x.IsDict()) { const NSc::TDict& dict = x.GetDict(); for (const auto& it : dict) { TKey key; NJsonConverters::FromString(it.first, key, validate); out.insert(key); } } } } ////////////////////////////////////////////////////////////////////// // TVector ////////////////////////////////////////////////////////////////////// template NSc::TValue ToTValue(const TVector& x) { NSc::TValue out; out.SetArray(); for (typename TVector::const_iterator it = x.begin(); it != x.end(); ++it) out.Push(NJsonConverters::ToTValue(*it)); return out; } template void FromTValue(const NSc::TValue& x, TVector& out, const bool validate) { if (validate) Y_ENSURE(x.IsArray() || x.IsNull(), "not valid input scheme"); out.clear(); if (x.IsArray()) { const NSc::TArray& arr = x.GetArray(); out.reserve(arr.size()); for (const auto& it : arr) { T val; NJsonConverters::FromTValue(it, val, validate); out.push_back(val); } } } ////////////////////////////////////////////////////////////////////// // THashMap & TMap ////////////////////////////////////////////////////////////////////// template NSc::TValue ToTValue(const THashMap& x) { return NPrivate::ToTValueDict(x); } template void FromTValue(const NSc::TValue& x, THashMap& out, const bool validate) { NPrivate::FromTValueDict(x, out, validate); } template NSc::TValue ToTValue(const TMap& x) { return NPrivate::ToTValueDict(x); } template void FromTValue(const NSc::TValue& x, TMap& out, const bool validate) { NPrivate::FromTValueDict(x, out, validate); } ////////////////////////////////////////////////////////////////////// // THashSet & TSet ////////////////////////////////////////////////////////////////////// template NSc::TValue ToTValue(const THashSet& x) { return NPrivate::ToTValueSet(x); } template void FromTValue(const NSc::TValue& x, THashSet& out, const bool validate) { NPrivate::FromTValueSet(x, out, validate); } template NSc::TValue ToTValue(const TSet& x) { return NPrivate::ToTValueSet(x); } template void FromTValue(const NSc::TValue& x, TSet& out, const bool validate) { NPrivate::FromTValueSet(x, out, validate); } ////////////////////////////////////////////////////////////////////// // std::pair ////////////////////////////////////////////////////////////////////// template NSc::TValue ToTValue(const std::pair& x) { NSc::TValue out; out.SetArray(); out.Push(NJsonConverters::ToTValue(x.first)); out.Push(NJsonConverters::ToTValue(x.second)); return out; } template void FromTValue(const NSc::TValue& x, std::pair& out, const bool validate) { if (validate) Y_ENSURE(x.IsArray() || x.IsNull(), "not valid input scheme"); if (x.IsArray()) { const NSc::TArray& arr = x.GetArray(); if (arr.size() == 2) { T1 val0; T2 val1; NJsonConverters::FromTValue(arr[0], val0, validate); NJsonConverters::FromTValue(arr[1], val1, validate); out.first = val0; out.second = val1; } } } ////////////////////////////////////////////////////////////////////// // global user functions ////////////////////////////////////////////////////////////////////// template TString ToJson(const T& val, const bool sort = false) { return NJsonConverters::ToTValue(val).ToJson(sort); } template T FromJson(const TStringBuf& json, bool validate = false) { NSc::TValue v = NSc::TValue::FromJson(json); T ret; NJsonConverters::FromTValue(v, ret, validate); return ret; } }