1 /* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #ifndef GRPC_CORE_LIB_JSON_JSON_H 20 #define GRPC_CORE_LIB_JSON_JSON_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <stdlib.h> 25 26 #include <map> 27 #include <string> 28 #include <vector> 29 30 #include "absl/strings/string_view.h" 31 32 #include "src/core/lib/iomgr/error.h" 33 34 namespace grpc_core { 35 36 // A JSON value, which can be any one of object, array, string, 37 // number, true, false, or null. 38 class Json { 39 public: 40 // TODO(roth): Currently, numbers are stored internally as strings, 41 // which makes the API a bit cumbersome to use. When we have time, 42 // consider whether there's a better alternative (e.g., maybe storing 43 // each numeric type as the native C++ type and automatically converting 44 // to string as needed). 45 enum class Type { 46 JSON_NULL, 47 JSON_TRUE, 48 JSON_FALSE, 49 NUMBER, 50 STRING, 51 OBJECT, 52 ARRAY 53 }; 54 55 using Object = std::map<std::string, Json>; 56 using Array = std::vector<Json>; 57 58 // Parses JSON string from json_str. On error, sets *error. 59 static Json Parse(absl::string_view json_str, grpc_error** error); 60 61 Json() = default; 62 63 // Copyable. Json(const Json & other)64 Json(const Json& other) { CopyFrom(other); } 65 Json& operator=(const Json& other) { 66 CopyFrom(other); 67 return *this; 68 } 69 70 // Moveable. Json(Json && other)71 Json(Json&& other) noexcept { MoveFrom(std::move(other)); } 72 Json& operator=(Json&& other) noexcept { 73 MoveFrom(std::move(other)); 74 return *this; 75 } 76 77 // Construct from copying a string. 78 // If is_number is true, the type will be NUMBER instead of STRING. 79 // NOLINTNEXTLINE(google-explicit-constructor) 80 Json(const std::string& string, bool is_number = false) 81 : type_(is_number ? Type::NUMBER : Type::STRING), string_value_(string) {} 82 Json& operator=(const std::string& string) { 83 type_ = Type::STRING; 84 string_value_ = string; 85 return *this; 86 } 87 88 // Same thing for C-style strings, both const and mutable. 89 // NOLINTNEXTLINE(google-explicit-constructor) 90 Json(const char* string, bool is_number = false) Json(std::string (string),is_number)91 : Json(std::string(string), is_number) {} 92 Json& operator=(const char* string) { 93 *this = std::string(string); 94 return *this; 95 } 96 // NOLINTNEXTLINE(google-explicit-constructor) 97 Json(char* string, bool is_number = false) Json(std::string (string),is_number)98 : Json(std::string(string), is_number) {} 99 Json& operator=(char* string) { 100 *this = std::string(string); 101 return *this; 102 } 103 104 // Construct by moving a string. 105 // NOLINTNEXTLINE(google-explicit-constructor) Json(std::string && string)106 Json(std::string&& string) 107 : type_(Type::STRING), string_value_(std::move(string)) {} 108 Json& operator=(std::string&& string) { 109 type_ = Type::STRING; 110 string_value_ = std::move(string); 111 return *this; 112 } 113 114 // Construct from bool. 115 // NOLINTNEXTLINE(google-explicit-constructor) Json(bool b)116 Json(bool b) : type_(b ? Type::JSON_TRUE : Type::JSON_FALSE) {} 117 Json& operator=(bool b) { 118 type_ = b ? Type::JSON_TRUE : Type::JSON_FALSE; 119 return *this; 120 } 121 122 // Construct from any numeric type. 123 template <typename NumericType> 124 // NOLINTNEXTLINE(google-explicit-constructor) Json(NumericType number)125 Json(NumericType number) 126 : type_(Type::NUMBER), string_value_(std::to_string(number)) {} 127 template <typename NumericType> 128 Json& operator=(NumericType number) { 129 type_ = Type::NUMBER; 130 string_value_ = std::to_string(number); 131 return *this; 132 } 133 134 // Construct by copying object. 135 // NOLINTNEXTLINE(google-explicit-constructor) Json(const Object & object)136 Json(const Object& object) : type_(Type::OBJECT), object_value_(object) {} 137 Json& operator=(const Object& object) { 138 type_ = Type::OBJECT; 139 object_value_ = object; 140 return *this; 141 } 142 143 // Construct by moving object. 144 // NOLINTNEXTLINE(google-explicit-constructor) Json(Object && object)145 Json(Object&& object) 146 : type_(Type::OBJECT), object_value_(std::move(object)) {} 147 Json& operator=(Object&& object) { 148 type_ = Type::OBJECT; 149 object_value_ = std::move(object); 150 return *this; 151 } 152 153 // Construct by copying array. 154 // NOLINTNEXTLINE(google-explicit-constructor) Json(const Array & array)155 Json(const Array& array) : type_(Type::ARRAY), array_value_(array) {} 156 Json& operator=(const Array& array) { 157 type_ = Type::ARRAY; 158 array_value_ = array; 159 return *this; 160 } 161 162 // Construct by moving array. 163 // NOLINTNEXTLINE(google-explicit-constructor) Json(Array && array)164 Json(Array&& array) : type_(Type::ARRAY), array_value_(std::move(array)) {} 165 Json& operator=(Array&& array) { 166 type_ = Type::ARRAY; 167 array_value_ = std::move(array); 168 return *this; 169 } 170 171 // Dumps JSON from value to string form. 172 std::string Dump(int indent = 0) const; 173 174 // Accessor methods. type()175 Type type() const { return type_; } string_value()176 const std::string& string_value() const { return string_value_; } mutable_string_value()177 std::string* mutable_string_value() { return &string_value_; } object_value()178 const Object& object_value() const { return object_value_; } mutable_object()179 Object* mutable_object() { return &object_value_; } array_value()180 const Array& array_value() const { return array_value_; } mutable_array()181 Array* mutable_array() { return &array_value_; } 182 183 bool operator==(const Json& other) const { 184 if (type_ != other.type_) return false; 185 switch (type_) { 186 case Type::NUMBER: 187 case Type::STRING: 188 if (string_value_ != other.string_value_) return false; 189 break; 190 case Type::OBJECT: 191 if (object_value_ != other.object_value_) return false; 192 break; 193 case Type::ARRAY: 194 if (array_value_ != other.array_value_) return false; 195 break; 196 default: 197 break; 198 } 199 return true; 200 } 201 202 bool operator!=(const Json& other) const { return !(*this == other); } 203 204 private: CopyFrom(const Json & other)205 void CopyFrom(const Json& other) { 206 type_ = other.type_; 207 switch (type_) { 208 case Type::NUMBER: 209 case Type::STRING: 210 string_value_ = other.string_value_; 211 break; 212 case Type::OBJECT: 213 object_value_ = other.object_value_; 214 break; 215 case Type::ARRAY: 216 array_value_ = other.array_value_; 217 break; 218 default: 219 break; 220 } 221 } 222 MoveFrom(Json && other)223 void MoveFrom(Json&& other) { 224 type_ = other.type_; 225 other.type_ = Type::JSON_NULL; 226 switch (type_) { 227 case Type::NUMBER: 228 case Type::STRING: 229 string_value_ = std::move(other.string_value_); 230 break; 231 case Type::OBJECT: 232 object_value_ = std::move(other.object_value_); 233 break; 234 case Type::ARRAY: 235 array_value_ = std::move(other.array_value_); 236 break; 237 default: 238 break; 239 } 240 } 241 242 Type type_ = Type::JSON_NULL; 243 std::string string_value_; 244 Object object_value_; 245 Array array_value_; 246 }; 247 248 } // namespace grpc_core 249 250 #endif /* GRPC_CORE_LIB_JSON_JSON_H */ 251