1 | // Copyright 2019 Google LLC |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include "nlohmann_json_serializer.h" |
16 | |
17 | #include "null_json_serializer.h" |
18 | |
19 | // Disable JSON exceptions. We should be guarding against any exceptions being |
20 | // fired in this file. |
21 | #define JSON_NOEXCEPTION 1 |
22 | #include <nlohmann/json.hpp> |
23 | |
24 | namespace dap { |
25 | namespace json { |
26 | |
27 | NlohmannDeserializer::NlohmannDeserializer(const std::string& str) |
28 | : json(new nlohmann::json(nlohmann::json::parse(str, nullptr, false))), |
29 | ownsJson(true) {} |
30 | |
31 | NlohmannDeserializer::NlohmannDeserializer(const nlohmann::json* json) |
32 | : json(json), ownsJson(false) {} |
33 | |
34 | NlohmannDeserializer::~NlohmannDeserializer() { |
35 | if (ownsJson) { |
36 | delete json; |
37 | } |
38 | } |
39 | |
40 | bool NlohmannDeserializer::deserialize(dap::boolean* v) const { |
41 | if (!json->is_boolean()) { |
42 | return false; |
43 | } |
44 | *v = json->get<bool>(); |
45 | return true; |
46 | } |
47 | |
48 | bool NlohmannDeserializer::deserialize(dap::integer* v) const { |
49 | if (!json->is_number_integer()) { |
50 | return false; |
51 | } |
52 | *v = json->get<int64_t>(); |
53 | return true; |
54 | } |
55 | |
56 | bool NlohmannDeserializer::deserialize(dap::number* v) const { |
57 | if (!json->is_number()) { |
58 | return false; |
59 | } |
60 | *v = json->get<double>(); |
61 | return true; |
62 | } |
63 | |
64 | bool NlohmannDeserializer::deserialize(dap::string* v) const { |
65 | if (!json->is_string()) { |
66 | return false; |
67 | } |
68 | *v = json->get<std::string>(); |
69 | return true; |
70 | } |
71 | |
72 | bool NlohmannDeserializer::deserialize(dap::object* v) const { |
73 | v->reserve(json->size()); |
74 | for (auto& el : json->items()) { |
75 | NlohmannDeserializer d(&el.value()); |
76 | dap::any val; |
77 | if (!d.deserialize(&val)) { |
78 | return false; |
79 | } |
80 | (*v)[el.key()] = val; |
81 | } |
82 | return true; |
83 | } |
84 | |
85 | bool NlohmannDeserializer::deserialize(dap::any* v) const { |
86 | if (json->is_boolean()) { |
87 | *v = dap::boolean(json->get<bool>()); |
88 | } else if (json->is_number_float()) { |
89 | *v = dap::number(json->get<double>()); |
90 | } else if (json->is_number_integer()) { |
91 | *v = dap::integer(json->get<int64_t>()); |
92 | } else if (json->is_string()) { |
93 | *v = json->get<std::string>(); |
94 | } else if (json->is_null()) { |
95 | *v = null(); |
96 | } else { |
97 | return false; |
98 | } |
99 | return true; |
100 | } |
101 | |
102 | size_t NlohmannDeserializer::count() const { |
103 | return json->size(); |
104 | } |
105 | |
106 | bool NlohmannDeserializer::array( |
107 | const std::function<bool(dap::Deserializer*)>& cb) const { |
108 | if (!json->is_array()) { |
109 | return false; |
110 | } |
111 | for (size_t i = 0; i < json->size(); i++) { |
112 | NlohmannDeserializer d(&(*json)[i]); |
113 | if (!cb(&d)) { |
114 | return false; |
115 | } |
116 | } |
117 | return true; |
118 | } |
119 | |
120 | bool NlohmannDeserializer::field( |
121 | const std::string& name, |
122 | const std::function<bool(dap::Deserializer*)>& cb) const { |
123 | if (!json->is_structured()) { |
124 | return false; |
125 | } |
126 | auto it = json->find(name); |
127 | if (it == json->end()) { |
128 | return cb(&NullDeserializer::instance); |
129 | } |
130 | auto obj = *it; |
131 | NlohmannDeserializer d(&obj); |
132 | return cb(&d); |
133 | } |
134 | |
135 | NlohmannSerializer::NlohmannSerializer() |
136 | : json(new nlohmann::json()), ownsJson(true) {} |
137 | |
138 | NlohmannSerializer::NlohmannSerializer(nlohmann::json* json) |
139 | : json(json), ownsJson(false) {} |
140 | |
141 | NlohmannSerializer::~NlohmannSerializer() { |
142 | if (ownsJson) { |
143 | delete json; |
144 | } |
145 | } |
146 | |
147 | std::string NlohmannSerializer::dump() const { |
148 | return json->dump(); |
149 | } |
150 | |
151 | bool NlohmannSerializer::serialize(dap::boolean v) { |
152 | *json = (bool)v; |
153 | return true; |
154 | } |
155 | |
156 | bool NlohmannSerializer::serialize(dap::integer v) { |
157 | *json = (int64_t)v; |
158 | return true; |
159 | } |
160 | |
161 | bool NlohmannSerializer::serialize(dap::number v) { |
162 | *json = (double)v; |
163 | return true; |
164 | } |
165 | |
166 | bool NlohmannSerializer::serialize(const dap::string& v) { |
167 | *json = v; |
168 | return true; |
169 | } |
170 | |
171 | bool NlohmannSerializer::serialize(const dap::object& v) { |
172 | for (auto& it : v) { |
173 | NlohmannSerializer s(&(*json)[it.first]); |
174 | if (!s.serialize(it.second)) { |
175 | return false; |
176 | } |
177 | } |
178 | return true; |
179 | } |
180 | |
181 | bool NlohmannSerializer::serialize(const dap::any& v) { |
182 | if (v.is<dap::boolean>()) { |
183 | *json = (bool)v.get<dap::boolean>(); |
184 | } else if (v.is<dap::integer>()) { |
185 | *json = (int64_t)v.get<dap::integer>(); |
186 | } else if (v.is<dap::number>()) { |
187 | *json = (double)v.get<dap::number>(); |
188 | } else if (v.is<dap::string>()) { |
189 | *json = v.get<dap::string>(); |
190 | } else if (v.is<dap::null>()) { |
191 | } else { |
192 | return false; |
193 | } |
194 | |
195 | return true; |
196 | } |
197 | |
198 | bool NlohmannSerializer::array( |
199 | size_t count, |
200 | const std::function<bool(dap::Serializer*)>& cb) { |
201 | *json = std::vector<int>(); |
202 | for (size_t i = 0; i < count; i++) { |
203 | NlohmannSerializer s(&(*json)[i]); |
204 | if (!cb(&s)) { |
205 | return false; |
206 | } |
207 | } |
208 | return true; |
209 | } |
210 | |
211 | bool NlohmannSerializer::object( |
212 | const std::function<bool(dap::FieldSerializer*)>& cb) { |
213 | struct FS : public FieldSerializer { |
214 | nlohmann::json* const json; |
215 | |
216 | FS(nlohmann::json* json) : json(json) {} |
217 | bool field(const std::string& name, const SerializeFunc& cb) override { |
218 | NlohmannSerializer s(&(*json)[name]); |
219 | auto res = cb(&s); |
220 | if (s.removed) { |
221 | json->erase(name); |
222 | } |
223 | return res; |
224 | } |
225 | }; |
226 | |
227 | *json = nlohmann::json({}, false, nlohmann::json::value_t::object); |
228 | FS fs{json}; |
229 | return cb(&fs); |
230 | } |
231 | |
232 | void NlohmannSerializer::remove() { |
233 | removed = true; |
234 | } |
235 | |
236 | } // namespace json |
237 | } // namespace dap |
238 | |