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