53 #include <rapidjson/document.h>
54 #include <rapidjson/stringbuffer.h>
55 #include <rapidjson/writer.h>
60 #include <type_traits>
68 std::shared_ptr<rapidjson::Document>
doc_;
70 rapidjson::Document::AllocatorType&
allo_;
76 :
doc_(std::make_shared<rapidjson::Document>())
97 void parse(
const std::string& json) {
98 if (
doc_->Parse(json).HasParseError()) {
99 throw std::runtime_error(
"failed to parse json");
104 if (
doc_->Parse(json).HasParseError()) {
105 throw std::runtime_error(
"failed to parse json");
109 void parse(
const char* json,
size_t len) {
110 if (
doc_->Parse(json, len).HasParseError()) {
111 throw std::runtime_error(
"failed to parse json");
116 rapidjson::StringBuffer buf;
117 rapidjson::Writer<rapidjson::StringBuffer> wr(buf);
119 return buf.GetString();
133 operator std::string()
const {
134 if (!
vptr_->IsString()) {
135 throw std::runtime_error(
"expected JSON field '" +
name_ +
139 return std::string{
vptr_->GetString(),
vptr_->GetStringLength()};
142 operator bool()
const {
143 if (!
vptr_->IsBool()) {
144 throw std::runtime_error(
"expected JSON field '" +
name_ +
145 "' to be Boolean but got [" +
148 return vptr_->GetBool();
151 template <
typename T>
153 static_assert((std::is_integral_v<T> && !std::is_same_v<
bool, std::remove_cv_t<T>>) ||
154 (std::is_floating_point_v<T>));
155 if constexpr (std::is_integral_v<T>) {
156 if constexpr (std::numeric_limits<T>::is_signed) {
157 if constexpr (
sizeof(
T) < 8) {
158 if (!
vptr_->IsInt()) {
159 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
160 "' to be signed integer from [" +
163 return vptr_->GetInt();
165 if (!
vptr_->IsInt64()) {
166 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
167 "' to be signed 64-bit integer from [" +
170 return vptr_->GetInt64();
173 if constexpr (
sizeof(
T) < 8) {
174 if (!
vptr_->IsUint()) {
175 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
176 "' to be unsigned integer from [" +
179 return vptr_->GetUint();
181 if (!
vptr_->IsUint64()) {
182 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
183 "' to be unsigned 64-bit integer from [" +
186 return vptr_->GetUint64();
189 }
else if constexpr (std::is_floating_point_v<T>) {
190 if (!
vptr_->IsDouble()) {
191 throw std::runtime_error(
"can't convert JSON field '" +
name_ +
192 "' to be floating point number from [" +
195 return vptr_->GetDouble();
205 *
vptr_ = rapidjson::Value().SetString(item,
allo_);
210 *
vptr_ = rapidjson::Value().SetString(item,
allo_);
215 vptr_->SetBool(item);
225 vptr_->SetInt64(item);
230 vptr_->SetUint(item);
235 vptr_->SetUint64(item);
241 if (!
vptr_->IsObject()) {
244 if (!
vptr_->HasMember(name)) {
246 rapidjson::Value(name,
allo_).Move(), rapidjson::Value().Move(),
allo_);
247 auto f =
vptr_->FindMember(name);
257 if (!
vptr_->IsObject()) {
258 throw std::runtime_error(
"JSON " +
kTypeNames[
vptr_->GetType()] +
" field '" +
259 name_ +
"' can't use operator []");
261 if (!
vptr_->HasMember(name)) {
262 throw std::runtime_error(
"JSON field '" + std::string(name) +
"' not found");
267 template <
typename T>
269 return operator[](static_cast<size_t>(index));
272 if (!
vptr_->IsArray()) {
275 if (index >=
vptr_->Size()) {
276 throw std::runtime_error(
"JSON array index " +
std::to_string(index) +
282 template <
typename T>
284 return operator[](static_cast<size_t>(index));
287 if (!
vptr_->IsArray()) {
288 throw std::runtime_error(
"JSON " +
kTypeNames[
vptr_->GetType()] +
" field '" +
289 name_ +
"' can't use operator []");
291 if (index >=
vptr_->Size()) {
292 throw std::runtime_error(
"JSON array index " +
std::to_string(index) +
300 {
"Null",
"False",
"True",
"Object",
"Array",
"String",
"Number"};
303 JSON(std::shared_ptr<rapidjson::Document> doc,
304 rapidjson::Value* vptr,
305 rapidjson::Document::AllocatorType& allo,
306 const std::string&
name)
312 template <
typename T>
314 template <
typename T>
317 template <
typename T>
319 template <
typename T>
335 template <
typename T>
337 return (*json.
vptr_ == value);
339 template <
typename T>
341 return (json == value);
344 template <
typename T>
346 return (*json.
vptr_ != value);
348 template <
typename T>
350 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[]