• 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) { 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