Skip to content

Instantly share code, notes, and snippets.

@jstefanelli
Last active February 25, 2025 16:52
Show Gist options
  • Select an option

  • Save jstefanelli/ae29ed95c45d0f30fbba7da394655df3 to your computer and use it in GitHub Desktop.

Select an option

Save jstefanelli/ae29ed95c45d0f30fbba7da394655df3 to your computer and use it in GitHub Desktop.
Super Primitive, header-only (almost), no-dependency, C++ JSON output "thing"
#pragma once
#include <variant>
#include <string>
#include <vector>
#include <unordered_map>
namespace json {
inline std::string util_replace(std::string haystack, const std::string_view& needle, const std::string_view& replaced_data) {
std::string::size_type pos = 0;
while ((pos = haystack.find(needle, pos)) != std::string::npos) {
haystack.replace(pos, needle.length(), replaced_data);
pos += replaced_data.length();
}
return haystack;
}
class Value;
using Object = std::unordered_map<std::string, Value>;
using Array = std::vector<Value>;
class Null {
public:
static Null value; ///Remember to implement this somewhere!
};
class Undefined {
public:
static Undefined value; //Remember to implement this somewhere!
};
class Value : public std::variant<std::string, double, bool, Null, Undefined, Object, Array> {
public:
template<typename T>
Value(T t) : std::variant<std::string, double, bool, Null, Undefined, Object, Array>(t) {
}
Value() : std::variant<std::string, double, bool, Null, Undefined, Object, Array>(Undefined::value) {
}
};
template<typename T>
inline void write(const Value& val, T& stream) {
auto idx = val.index();
if (idx == 0) {
const auto& str = std::get<std::string>(val);
auto final_str = util_replace(str, "\"", "\\\"");
stream << "\"" << final_str << "\"";
} else if (idx == 1) {
stream << std::get<double>(val);
} else if (idx == 2) {
stream << (std::get<bool>(val) ? "true" : "false");
} else if (idx == 3) {
stream << "null";
} else if (idx == 4) {
stream << "undefined";
} else if (idx == 5) {
stream << "{ ";
const auto& map = std::get<Object>(val);
for (auto it = map.cbegin(); it != map.cend(); it++) {
if (it != map.cbegin()) {
stream << ", ";
}
auto final_label = util_replace(it->first, "\"", "\\\"");
stream << "\"" << final_label << "\": ";
write(it->second, stream);
}
stream << " }";
} else if (idx == 6) {
stream << "[ ";
const auto& vec = std::get<Array>(val);
for(auto it = vec.cbegin(); it != vec.cend(); it++) {
if (it != vec.cbegin()) {
stream << ", ";
}
write(*it, stream);
}
stream << " ]";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment