• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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