I wrote the following code to represent JSON data in C++. I got some vague review comments that this may not be optimal and if we decide to parse JSON data directly into this structure then we might have trouble. I did not quite get the terse comments, so shall reproduce my code here and hope to hear what is wrong.
#define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
#include <boost/variant.hpp>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <iomanip>
#define STR_(x) std::string(x)
struct JSONNullType {};
typedef boost::make_recursive_variant<
std::string,
long,
double,
std::map<std::string, boost::recursive_variant_>,
std::vector<boost::recursive_variant_>,
bool,
JSONNullType>::type JSONValue;
typedef std::vector<JSONValue> JSONArray;
typedef std::map<std::string, JSONValue> JSONObject;
struct JSONPrintVisitor : public boost::static_visitor<void>
{
void operator()(const JSONArray& array) const
{
std::cout << '[';
if (!array.empty()) {
boost::apply_visitor(*this, array[0]);
std::for_each(array.begin() + 1, array.end(),
[this](const JSONValue& v) {
std::cout << ',';
boost::apply_visitor(*this, v);
});
}
std::cout << ']' << std::endl;
}
void operator()(const JSONObject& object) const
{
std::cout << '{';
if (!object.empty()) {
const auto& kv_pair = *(object.begin());
std::cout << '"' << kv_pair.first << '"';
std::cout << ':';
boost::apply_visitor(*this, kv_pair.second);
auto it = object.begin();
std::for_each(++it, object.end(),
[this](const JSONObject::value_type& v) {
std::cout << ',';
std::cout << '"' << v.first << '"';
std::cout << ':';
boost::apply_visitor(*this, v.second);
});
}
std::cout << '}';
}
void operator() (const std::string& str) const
{
std::cout << '"' << str << '"';
}
void operator() (const JSONNullType&) const
{
std::cout << "null";
}
template <typename T>
void operator()(const T& value) const
{
std::cout << std::boolalpha << value;
}
};
int main()
{
JSONValue vt = JSONArray();
JSONArray *array = boost::get<JSONArray>(&vt);
JSONValue person1 = JSONObject();
JSONValue person2 = JSONObject();
JSONValue person3 = JSONObject();
JSONValue person4 = JSONObject();
JSONObject *pp1 = boost::get<JSONObject>(&person1),
*pp2 = boost::get<JSONObject>(&person2),
*pp3 = boost::get<JSONObject>(&person3);
(*pp1)["name"] = STR_("Baba O'Riley");
(*pp1)["profession"] = STR_("farmer");
(*pp1)["age"] = 21L;
(*pp1)["favourite"] = STR_("Baba ganoush");
(*pp1)["height"] = 176.1;
(*pp2)["name"] = STR_("Stuart Little");
(*pp2)["profession"] = STR_("good-boy mouse");
(*pp2)["age"] = 4L;
(*pp2)["favourite"] = STR_("Gouda");
(*pp2)["height"] = 11.0;
(*pp3)["name"] = STR_("Howard Roark");
(*pp3)["profession"] = STR_("architect");
(*pp3)["age"] = 32L;
(*pp3)["favourite"] = STR_("Eggs benedict");
(*pp3)["height"] = 185.0;
array->push_back(person1);
array->push_back(person2);
array->push_back(person3);
boost::apply_visitor(JSONPrintVisitor(), vt);
}