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