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) { MoveFrom(std::move(other)); } 72 Json& operator=(Json&& other) { 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 Json(const std::string& string, bool is_number = false) 80 : type_(is_number ? Type::NUMBER : Type::STRING), string_value_(string) {} 81 Json& operator=(const std::string& string) { 82 type_ = Type::STRING; 83 string_value_ = string; 84 return *this; 85 } 86 87 // Same thing for C-style strings, both const and mutable. 88 Json(const char* string, bool is_number = false) Json(std::string (string),is_number)89 : Json(std::string(string), is_number) {} 90 Json& operator=(const char* string) { 91 *this = std::string(string); 92 return *this; 93 } 94 Json(char* string, bool is_number = false) Json(std::string (string),is_number)95 : Json(std::string(string), is_number) {} 96 Json& operator=(char* string) { 97 *this = std::string(string); 98 return *this; 99 } 100 101 // Construct by moving a string. Json(std::string && string)102 Json(std::string&& string) 103 : type_(Type::STRING), string_value_(std::move(string)) {} 104 Json& operator=(std::string&& string) { 105 type_ = Type::STRING; 106 string_value_ = std::move(string); 107 return *this; 108 } 109 110 // Construct from bool. Json(bool b)111 Json(bool b) : type_(b ? Type::JSON_TRUE : Type::JSON_FALSE) {} 112 Json& operator=(bool b) { 113 type_ = b ? Type::JSON_TRUE : Type::JSON_FALSE; 114 return *this; 115 } 116 117 // Construct from any numeric type. 118 template <typename NumericType> Json(NumericType number)119 Json(NumericType number) 120 : type_(Type::NUMBER), string_value_(std::to_string(number)) {} 121 template <typename NumericType> 122 Json& operator=(NumericType number) { 123 type_ = Type::NUMBER; 124 string_value_ = std::to_string(number); 125 return *this; 126 } 127 128 // Construct by copying object. Json(const Object & object)129 Json(const Object& object) : type_(Type::OBJECT), object_value_(object) {} 130 Json& operator=(const Object& object) { 131 type_ = Type::OBJECT; 132 object_value_ = object; 133 return *this; 134 } 135 136 // Construct by moving object. Json(Object && object)137 Json(Object&& object) 138 : type_(Type::OBJECT), object_value_(std::move(object)) {} 139 Json& operator=(Object&& object) { 140 type_ = Type::OBJECT; 141 object_value_ = std::move(object); 142 return *this; 143 } 144 145 // Construct by copying array. Json(const Array & array)146 Json(const Array& array) : type_(Type::ARRAY), array_value_(array) {} 147 Json& operator=(const Array& array) { 148 type_ = Type::ARRAY; 149 array_value_ = array; 150 return *this; 151 } 152 153 // Construct by moving array. Json(Array && array)154 Json(Array&& array) : type_(Type::ARRAY), array_value_(std::move(array)) {} 155 Json& operator=(Array&& array) { 156 type_ = Type::ARRAY; 157 array_value_ = std::move(array); 158 return *this; 159 } 160 161 // Dumps JSON from value to string form. 162 std::string Dump(int indent = 0) const; 163 164 // Accessor methods. type()165 Type type() const { return type_; } string_value()166 const std::string& string_value() const { return string_value_; } mutable_string_value()167 std::string* mutable_string_value() { return &string_value_; } object_value()168 const Object& object_value() const { return object_value_; } mutable_object()169 Object* mutable_object() { return &object_value_; } array_value()170 const Array& array_value() const { return array_value_; } mutable_array()171 Array* mutable_array() { return &array_value_; } 172 173 bool operator==(const Json& other) const { 174 if (type_ != other.type_) return false; 175 switch (type_) { 176 case Type::NUMBER: 177 case Type::STRING: 178 if (string_value_ != other.string_value_) return false; 179 break; 180 case Type::OBJECT: 181 if (object_value_ != other.object_value_) return false; 182 break; 183 case Type::ARRAY: 184 if (array_value_ != other.array_value_) return false; 185 break; 186 default: 187 break; 188 } 189 return true; 190 } 191 192 bool operator!=(const Json& other) const { return !(*this == other); } 193 194 private: CopyFrom(const Json & other)195 void CopyFrom(const Json& other) { 196 type_ = other.type_; 197 switch (type_) { 198 case Type::NUMBER: 199 case Type::STRING: 200 string_value_ = other.string_value_; 201 break; 202 case Type::OBJECT: 203 object_value_ = other.object_value_; 204 break; 205 case Type::ARRAY: 206 array_value_ = other.array_value_; 207 break; 208 default: 209 break; 210 } 211 } 212 MoveFrom(Json && other)213 void MoveFrom(Json&& other) { 214 type_ = other.type_; 215 other.type_ = Type::JSON_NULL; 216 switch (type_) { 217 case Type::NUMBER: 218 case Type::STRING: 219 string_value_ = std::move(other.string_value_); 220 break; 221 case Type::OBJECT: 222 object_value_ = std::move(other.object_value_); 223 break; 224 case Type::ARRAY: 225 array_value_ = std::move(other.array_value_); 226 break; 227 default: 228 break; 229 } 230 } 231 232 Type type_ = Type::JSON_NULL; 233 std::string string_value_; 234 Object object_value_; 235 Array array_value_; 236 }; 237 238 } // namespace grpc_core 239 240 #endif /* GRPC_CORE_LIB_JSON_JSON_H */ 241