I want to write a serial of template functions to serialize and deserialize objects. I've finished the serialization part and everything works:
#ifndef SERIALIZE_H
#define SERIALIZE_H
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <memory>
inline std::string to_json(int value) {
return std::to_string(value);
}
inline std::string to_json(long value) {
return std::to_string(value);
}
inline std::string to_json(double value) {
return std::to_string(value);
}
inline std::string to_json(const std::string& myStr) {
return "\"" + myStr + "\"";
}
template <typename T>
std::string to_json(const std::vector<T>& vec) {
std::string json("[");
for(auto &i : vec) {
json += to_json(i);
json += ",";
}
if (!vec.empty()) json.pop_back();
json += "]";
return json;
}
template <typename T>
std::string to_json(const std::unordered_set<T>& mySet) {
std::string json("[");
for(const auto& i : mySet) {
json += to_json(i);
json += ",";
}
if (!mySet.empty()) json.pop_back();
json += "]";
return json;
}
template <typename K, typename V>
std::string to_json(const std::unordered_map<K, V>& myMap) {
std::string json("{");
for(const auto& i : myMap) {
json += to_json(i.first);
json += ":";
json += to_json(i.second);
json += ",";
}
if (!myMap.empty()) json.pop_back();
json += "}";
return json;
}
#endif //SERIALIZE_H
This serialize.h
can serialize all kinds of combinations, such as unordered_map<string, vector<int>>
.
Now I don't know how to implement deserialization functions recursively to support arbitrary combinations.
The following is my deserialize.h
which doesn't work:
#ifndef DESERIALIZE_H
#define DESERIALIZE_H
#include <string>
#include <rapidjson/document.h>
template<typename T>
T from_json(const std::string &json);
template<>
int from_json(const std::string &json) {
return std::stoi(json);
}
template<>
long from_json(const std::string &json) {
return std::stol(json);
}
template<>
double from_json(const std::string &json) {
return std::stod(json);
}
template<>
std::string from_json(const std::string &json) {
return json.substr(1, json.size()-1);
}
//
template<typename T>
std::vector<T> from_json(const std::string& json) {
rapidjson::Value jsonValue;
{
const std::string &input = "{\"input\":" + json + "}";
rapidjson::Document document;
document.Parse(input.c_str());
jsonValue = document["input"];
};
std::vector<T> vec;
assert(jsonValue.IsArray());
for (rapidjson::SizeType i = 0; i < jsonValue.Size(); i++) {
int element = from_json<T>(std::string(jsonValue[i].GetString()));
vec.push_back(element);
}
return vec;
}
#endif //DESERIALIZE_H
rapidjson
is a C++ JSON library, https://github.com/miloyip/rapidjson
Then if I try to deserialize a JSON string:
#include "deserialize.h>
int main() {
auto vec1 = from_json<std::vector<int>>(std::string("[1,2,3]"));
return 0;
}
It will throw out compilation errors:
error: call of overloaded ‘from_json(std::string)’ is ambiguous
It seems there is no way to implement deserialization function as easily as serialization.
Any ideas?
You are trying to overload the same function (from_json(...)) with the same arguments and a different return type each time. This is not legal. For overloading, you need different argument types or argument number.
maybe try this, or at least this should be the general idea:
I am sure there are errors, but I think this way it can work (if you fix them)