1 // 2 // Copyright 2015 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef GRPC_SUPPORT_JSON_H 18 #define GRPC_SUPPORT_JSON_H 19 20 #include <grpc/support/port_platform.h> 21 #include <stdint.h> 22 23 #include <map> 24 #include <string> 25 #include <utility> 26 #include <vector> 27 28 #include "absl/strings/str_cat.h" 29 #include "absl/types/variant.h" 30 31 namespace grpc_core { 32 namespace experimental { 33 34 // A JSON value, which can be any one of null, boolean, number, string, 35 // object, or array. 36 class Json { 37 public: 38 // The JSON type. 39 enum class Type { 40 kNull, // No payload. Default type when using the zero-arg ctor. 41 kBoolean, // Use boolean() for payload. 42 kNumber, // Numbers are stored in string form to avoid precision 43 // and integer capacity issues. Use string() for payload. 44 kString, // Use string() for payload. 45 kObject, // Use object() for payload. 46 kArray, // Use array() for payload. 47 }; 48 49 using Object = std::map<std::string, Json>; 50 using Array = std::vector<Json>; 51 52 // Factory method for kBoolean. FromBool(bool b)53 static Json FromBool(bool b) { 54 Json json; 55 json.value_ = b; 56 return json; 57 } 58 59 // Factory methods for kNumber. FromNumber(const std::string & str)60 static Json FromNumber(const std::string& str) { 61 Json json; 62 json.value_ = NumberValue{str}; 63 return json; 64 } FromNumber(const char * str)65 static Json FromNumber(const char* str) { 66 Json json; 67 json.value_ = NumberValue{std::string(str)}; 68 return json; 69 } FromNumber(std::string && str)70 static Json FromNumber(std::string&& str) { 71 Json json; 72 json.value_ = NumberValue{std::move(str)}; 73 return json; 74 } FromNumber(int32_t value)75 static Json FromNumber(int32_t value) { 76 Json json; 77 json.value_ = NumberValue{absl::StrCat(value)}; 78 return json; 79 } FromNumber(uint32_t value)80 static Json FromNumber(uint32_t value) { 81 Json json; 82 json.value_ = NumberValue{absl::StrCat(value)}; 83 return json; 84 } FromNumber(int64_t value)85 static Json FromNumber(int64_t value) { 86 Json json; 87 json.value_ = NumberValue{absl::StrCat(value)}; 88 return json; 89 } FromNumber(uint64_t value)90 static Json FromNumber(uint64_t value) { 91 Json json; 92 json.value_ = NumberValue{absl::StrCat(value)}; 93 return json; 94 } FromNumber(double value)95 static Json FromNumber(double value) { 96 Json json; 97 json.value_ = NumberValue{absl::StrCat(value)}; 98 return json; 99 } 100 101 // Factory methods for kString. FromString(const std::string & str)102 static Json FromString(const std::string& str) { 103 Json json; 104 json.value_ = str; 105 return json; 106 } FromString(const char * str)107 static Json FromString(const char* str) { 108 Json json; 109 json.value_ = std::string(str); 110 return json; 111 } FromString(std::string && str)112 static Json FromString(std::string&& str) { 113 Json json; 114 json.value_ = std::move(str); 115 return json; 116 } 117 118 // Factory methods for kObject. FromObject(const Object & object)119 static Json FromObject(const Object& object) { 120 Json json; 121 json.value_ = object; 122 return json; 123 } FromObject(Object && object)124 static Json FromObject(Object&& object) { 125 Json json; 126 json.value_ = std::move(object); 127 return json; 128 } 129 130 // Factory methods for kArray. FromArray(const Array & array)131 static Json FromArray(const Array& array) { 132 Json json; 133 json.value_ = array; 134 return json; 135 } FromArray(Array && array)136 static Json FromArray(Array&& array) { 137 Json json; 138 json.value_ = std::move(array); 139 return json; 140 } 141 142 Json() = default; 143 144 // Copyable. 145 Json(const Json& other) = default; 146 Json& operator=(const Json& other) = default; 147 148 // Moveable. Json(Json && other)149 Json(Json&& other) noexcept : value_(std::move(other.value_)) { 150 other.value_ = absl::monostate(); 151 } 152 Json& operator=(Json&& other) noexcept { 153 value_ = std::move(other.value_); 154 other.value_ = absl::monostate(); 155 return *this; 156 } 157 158 // Returns the JSON type. type()159 Type type() const { 160 struct ValueFunctor { 161 Json::Type operator()(const absl::monostate&) { return Type::kNull; } 162 Json::Type operator()(bool) { return Type::kBoolean; } 163 Json::Type operator()(const NumberValue&) { return Type::kNumber; } 164 Json::Type operator()(const std::string&) { return Type::kString; } 165 Json::Type operator()(const Object&) { return Type::kObject; } 166 Json::Type operator()(const Array&) { return Type::kArray; } 167 }; 168 return absl::visit(ValueFunctor(), value_); 169 } 170 171 // Payload accessor for kBoolean. 172 // Must not be called for other types. boolean()173 bool boolean() const { return absl::get<bool>(value_); } 174 175 // Payload accessor for kNumber or kString. 176 // Must not be called for other types. string()177 const std::string& string() const { 178 const NumberValue* num = absl::get_if<NumberValue>(&value_); 179 if (num != nullptr) return num->value; 180 return absl::get<std::string>(value_); 181 } 182 183 // Payload accessor for kObject. 184 // Must not be called for other types. object()185 const Object& object() const { return absl::get<Object>(value_); } 186 187 // Payload accessor for kArray. 188 // Must not be called for other types. array()189 const Array& array() const { return absl::get<Array>(value_); } 190 191 bool operator==(const Json& other) const { return value_ == other.value_; } 192 bool operator!=(const Json& other) const { return !(*this == other); } 193 194 private: 195 struct NumberValue { 196 std::string value; 197 198 bool operator==(const NumberValue& other) const { 199 return value == other.value; 200 } 201 }; 202 using Value = absl::variant<absl::monostate, // kNull 203 bool, // kBoolean 204 NumberValue, // kNumber 205 std::string, // kString 206 Object, // kObject 207 Array>; // kArray 208 Json(Value value)209 explicit Json(Value value) : value_(std::move(value)) {} 210 211 Value value_; 212 }; 213 214 } // namespace experimental 215 } // namespace grpc_core 216 217 #endif // GRPC_SUPPORT_JSON_H 218