51 #include <rapidjson/document.h>
52 #include <rapidjson/stringbuffer.h>
53 #include <rapidjson/writer.h>
58 #include <type_traits>
66 std::shared_ptr<rapidjson::Document>
doc_;
68 rapidjson::Document::AllocatorType&
allo_;
74 :
doc_(std::make_shared<rapidjson::Document>())
95 void parse(
const std::string& json) {
96 if (
doc_->Parse(json).HasParseError()) {
97 throw std::runtime_error(
"failed to parse json");
102 if (
doc_->Parse(json).HasParseError()) {
103 throw std::runtime_error(
"failed to parse json");
107 void parse(
const char* json,
size_t len) {
108 if (
doc_->Parse(json, len).HasParseError()) {
109 throw std::runtime_error(
"failed to parse json");
114 rapidjson::StringBuffer buf;
115 rapidjson::Writer<rapidjson::StringBuffer> wr(buf);
117 return buf.GetString();
131 operator std::string()
const {
132 if (!
vptr_->IsString()) {
133 throw std::runtime_error(
"expected JSON field '" +
name_ +
137 return std::string{
vptr_->GetString(),
vptr_->GetStringLength()};
140 operator bool()
const {
141 if (!
vptr_->IsBool()) {
142 throw std::runtime_error(
"expected JSON field '" +
name_ +
143 "' to be Boolean but got [" +
146 return vptr_->GetBool();
149 template <
typename T>
151 static_assert((std::is_integral_v<T> && !std::is_same_v<
bool, std::remove_cv_t<T>>) ||
152 (std::is_floating_point_v<T>));
153 if constexpr (std::is_integral_v<T>) {
154 if constexpr (std::numeric_limits<T>::is_signed) {
155 if constexpr (
sizeof(
T) < 8) {
156 if (!
vptr_->IsInt()) {
157 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
158 "' to be signed integer from [" +
161 return vptr_->GetInt();
163 if (!
vptr_->IsInt64()) {
164 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
165 "' to be signed 64-bit integer from [" +
168 return vptr_->GetInt64();
171 if constexpr (
sizeof(
T) < 8) {
172 if (!
vptr_->IsUint()) {
173 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
174 "' to be unsigned integer from [" +
177 return vptr_->GetUint();
179 if (!
vptr_->IsUint64()) {
180 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
181 "' to be unsigned 64-bit integer from [" +
184 return vptr_->GetUint64();
187 }
else if constexpr (std::is_floating_point_v<T>) {
188 if (!
vptr_->IsDouble()) {
189 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
190 "' to be floating point number from [" +
193 return vptr_->GetDouble();
203 *
vptr_ = rapidjson::Value().SetString(item,
allo_);
208 *
vptr_ = rapidjson::Value().SetString(item,
allo_);
213 vptr_->SetBool(item);
223 vptr_->SetInt64(item);
228 vptr_->SetUint(item);
233 vptr_->SetUint64(item);
239 if (!
vptr_->IsObject()) {
242 if (!
vptr_->HasMember(name)) {
244 rapidjson::Value(name,
allo_).Move(), rapidjson::Value().Move(),
allo_);
245 auto f =
vptr_->FindMember(name);
255 if (!
vptr_->IsObject()) {
256 throw std::runtime_error(
"JSON " +
kTypeNames[
vptr_->GetType()] +
" field '" +
257 name_ +
"' can't use operator []");
259 if (!
vptr_->HasMember(name)) {
260 throw std::runtime_error(
"JSON field '" + std::string(name) +
"' not found");
265 template <
typename T>
267 return operator[](static_cast<size_t>(index));
270 if (!
vptr_->IsArray()) {
273 if (index >=
vptr_->Size()) {
274 throw std::runtime_error(
"JSON array index " +
std::to_string(index) +
280 template <
typename T>
282 return operator[](static_cast<size_t>(index));
285 if (!
vptr_->IsArray()) {
286 throw std::runtime_error(
"JSON " +
kTypeNames[
vptr_->GetType()] +
" field '" +
287 name_ +
"' can't use operator []");
289 if (index >=
vptr_->Size()) {
290 throw std::runtime_error(
"JSON array index " +
std::to_string(index) +
298 {
"Null",
"False",
"True",
"Object",
"Array",
"String",
"Number"};
301 JSON(std::shared_ptr<rapidjson::Document> doc,
302 rapidjson::Value* vptr,
303 rapidjson::Document::AllocatorType& allo,
304 const std::string&
name)
310 template <
typename T>
312 template <
typename T>
315 template <
typename T>
317 template <
typename T>
333 template <
typename T>
335 return (*json.
vptr_ == value);
337 template <
typename T>
339 return (json == value);
342 template <
typename T>
344 return (*json.
vptr_ != value);
346 template <
typename T>
348 return (json != value);
JSON(const std::string &json)
JSON & operator=(const JSON &peer)
std::shared_ptr< rapidjson::Document > doc_
std::string getType() const
friend bool operator!=(const JSON &json1, const JSON &json2)
JSON operator[](const char *name)
void parse(const std::string &json)
JSON & operator=(uint64_t item)
JSON & operator=(int64_t item)
JSON(const char *json, size_t len)
JSON & operator=(bool item)
JSON operator[](const char *name) const
JSON & operator=(const std::string &item)
std::string stringify() const
JSON & operator=(uint32_t item)
JSON operator[](T index) const
bool hasMember(const std::string &name) const
JSON operator[](size_t index) const
JSON & operator=(const char *item)
JSON operator[](const std::string &name) const
JSON operator[](size_t index)
JSON(std::shared_ptr< rapidjson::Document > doc, rapidjson::Value *vptr, rapidjson::Document::AllocatorType &allo, const std::string &name)
friend bool operator==(const JSON &json1, const JSON &json2)
JSON operator[](const std::string &name)
rapidjson::Document::AllocatorType & allo_
JSON & operator=(int32_t item)
bool operator==(const JSON &json1, const JSON &json2)
bool operator!=(const JSON &json1, const JSON &json2)
void parse(const char *json, size_t len)
void parse(const char *json)
static std::string kTypeNames[]