Skip to content

Instantly share code, notes, and snippets.

@samolisov
Created July 23, 2019 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samolisov/0985d264223525e7c39b330dce963cfa to your computer and use it in GitHub Desktop.
Save samolisov/0985d264223525e7c39b330dce963cfa to your computer and use it in GitHub Desktop.
A short demo how to use a recursive std::variant
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <variant>
#include <vector>
struct JSONValue;
class JSONStringVisitor;
class JSONSerializer;
struct JSONValue {
std::variant<
std::nullptr_t,
bool,
double,
std::string,
std::vector<JSONValue>,
std::map<std::string, JSONValue>
> value;
JSONValue(std::nullptr_t np): value(np) {}
JSONValue(bool bval): value(bval) {}
JSONValue(double dval): value(dval) {}
JSONValue(const char *str): value(std::string(str)) {}
JSONValue(const std::string& str): value(str) {}
JSONValue(const std::vector<JSONValue>& vec): value(vec) {}
JSONValue(const std::map<std::string, JSONValue>& map): value(map) {}
};
class JSONStringVisitor {
public:
JSONStringVisitor() : ss_(std::string()) {}
std::string str() { return ss_.str(); }
void operator()(std::nullptr_t) { ss_ << "null"; }
void operator()(bool value) { ss_ << std::boolalpha << value << std::noboolalpha; }
void operator()(double value) { ss_ << value; }
void operator()(const std::string& str) { ss_ << '"' << str << '"'; }
void operator()(const std::vector<JSONValue>& vec) {
ss_ << '[';
auto size = vec.size();
for (auto i = 0; i < size; ++i) {
std::visit(*this, vec[i].value);
if (i < size - 1)
ss_ << ", ";
}
ss_ << ']';
}
void operator()(const std::map<std::string, JSONValue>& map) {
size_t processed = 0;
size_t size = map.size();
ss_ << '{';
for (auto&& [key, value] : map) {
ss_ << '"' << key << "\" : ";
std::visit(*this, value.value);
if (++processed < size)
ss_ << ", ";
}
ss_ << '}';
}
private:
std::stringstream ss_;
};
class JSONSerializer {
public:
static std::string serialize(const JSONValue& json) {
JSONStringVisitor string_visitor{};
std::visit(string_visitor, json.value);
return string_visitor.str();
}
};
int main() {
JSONValue str{ "hello world" };
std::cout << JSONSerializer::serialize(str) << std::endl;
JSONValue json{
std::vector<JSONValue>{
std::map<std::string, JSONValue>{
{"name", "Joe"},
{"sername", "Smith"},
{"score", nullptr},
{"rights", std::vector<JSONValue>{"admin", 2.0, 3.14, true, nullptr}}
},
std::map<std::string, JSONValue>{
{"name", "Samanta"},
{"sername", "Orion"},
{"score", 99.3},
{"rights", std::vector<JSONValue>{"user", 5.15, 4.2, false}}
}
}
};
std::cout << JSONSerializer::serialize(json) << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment