Line data Source code
1 : #include "source/common/json/json_internal.h"
2 :
3 : #include <cstdint>
4 : #include <fstream>
5 : #include <limits>
6 : #include <map>
7 : #include <sstream>
8 : #include <stack>
9 : #include <string>
10 : #include <vector>
11 :
12 : #include "source/common/common/assert.h"
13 : #include "source/common/common/fmt.h"
14 : #include "source/common/common/hash.h"
15 : #include "source/common/common/utility.h"
16 : #include "source/common/protobuf/utility.h"
17 :
18 : // Do not let nlohmann/json leak outside of this file.
19 : #include "include/nlohmann/json.hpp"
20 :
21 : #include "absl/strings/match.h"
22 :
23 : namespace Envoy {
24 : namespace Json {
25 : namespace Nlohmann {
26 :
27 : namespace {
28 :
29 : /**
30 : * Internal representation of Object.
31 : */
32 : class Field;
33 : using FieldSharedPtr = std::shared_ptr<Field>;
34 :
35 : class Field : public Object {
36 : public:
37 57591 : void setLineNumberStart(uint64_t line_number) { line_number_start_ = line_number; }
38 25219 : void setLineNumberEnd(uint64_t line_number) { line_number_end_ = line_number; }
39 :
40 : // Container factories for handler.
41 17890 : static FieldSharedPtr createObject() { return FieldSharedPtr{new Field(Type::Object)}; }
42 7329 : static FieldSharedPtr createArray() { return FieldSharedPtr{new Field(Type::Array)}; }
43 0 : static FieldSharedPtr createNull() { return FieldSharedPtr{new Field(Type::Null)}; }
44 :
45 51876 : bool isArray() const override { return type_ == Type::Array; }
46 82484 : bool isObject() const override { return type_ == Type::Object; }
47 :
48 : // Value factory.
49 32372 : template <typename T> static FieldSharedPtr createValue(T value) {
50 32372 : return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51 32372 : }
52 :
53 17779 : void append(FieldSharedPtr field_ptr) {
54 17779 : checkType(Type::Array);
55 17779 : value_.array_value_.push_back(field_ptr);
56 17779 : }
57 39672 : void insert(const std::string& key, FieldSharedPtr field_ptr) {
58 39672 : checkType(Type::Object);
59 39672 : value_.object_value_[key] = field_ptr;
60 39672 : }
61 :
62 : uint64_t hash() const override;
63 :
64 : absl::StatusOr<ValueType> getValue(const std::string& name) const override;
65 : bool getBoolean(const std::string& name) const override;
66 : bool getBoolean(const std::string& name, bool default_value) const override;
67 : double getDouble(const std::string& name) const override;
68 : double getDouble(const std::string& name, double default_value) const override;
69 : int64_t getInteger(const std::string& name) const override;
70 : int64_t getInteger(const std::string& name, int64_t default_value) const override;
71 : ObjectSharedPtr getObject(const std::string& name, bool allow_empty) const override;
72 : absl::StatusOr<ObjectSharedPtr> getObjectNoThrow(const std::string& name,
73 : bool allow_empty) const override;
74 : std::vector<ObjectSharedPtr> getObjectArray(const std::string& name,
75 : bool allow_empty) const override;
76 : std::string getString(const std::string& name) const override;
77 : std::string getString(const std::string& name, const std::string& default_value) const override;
78 : std::vector<std::string> getStringArray(const std::string& name, bool allow_empty) const override;
79 : std::vector<ObjectSharedPtr> asObjectArray() const override;
80 144 : std::string asString() const override { return stringValue(); }
81 : std::string asJsonString() const override;
82 :
83 : bool empty() const override;
84 : bool hasObject(const std::string& name) const override;
85 : void iterate(const ObjectCallback& callback) const override;
86 : void validateSchema(const std::string&) const override;
87 :
88 : private:
89 : enum class Type {
90 : Array,
91 : Boolean,
92 : Double,
93 : Integer,
94 : Null,
95 : Object,
96 : String,
97 : };
98 0 : static const char* typeAsString(Type t) {
99 0 : switch (t) {
100 0 : case Type::Array:
101 0 : return "Array";
102 0 : case Type::Boolean:
103 0 : return "Boolean";
104 0 : case Type::Double:
105 0 : return "Double";
106 0 : case Type::Integer:
107 0 : return "Integer";
108 0 : case Type::Null:
109 0 : return "Null";
110 0 : case Type::Object:
111 0 : return "Object";
112 0 : case Type::String:
113 0 : return "String";
114 0 : }
115 :
116 0 : return "";
117 0 : }
118 :
119 : struct Value {
120 : std::vector<FieldSharedPtr> array_value_;
121 : bool boolean_value_;
122 : double double_value_;
123 : int64_t integer_value_;
124 : std::map<std::string, FieldSharedPtr> object_value_;
125 : std::string string_value_;
126 : };
127 :
128 25219 : explicit Field(Type type) : type_(type) {}
129 31470 : explicit Field(const std::string& value) : type_(Type::String) { value_.string_value_ = value; }
130 712 : explicit Field(int64_t value) : type_(Type::Integer) { value_.integer_value_ = value; }
131 0 : explicit Field(double value) : type_(Type::Double) { value_.double_value_ = value; }
132 190 : explicit Field(bool value) : type_(Type::Boolean) { value_.boolean_value_ = value; }
133 :
134 82962 : bool isType(Type type) const { return type == type_; }
135 82962 : void checkType(Type type) const {
136 82962 : if (!isType(type)) {
137 0 : throwExceptionOrPanic(
138 0 : Exception,
139 0 : fmt::format(
140 0 : "JSON field from line {} accessed with type '{}' does not match actual type '{}'.",
141 0 : line_number_start_, typeAsString(type), typeAsString(type_)));
142 0 : }
143 82962 : }
144 :
145 : // Value return type functions.
146 144 : std::string stringValue() const {
147 144 : checkType(Type::String);
148 144 : return value_.string_value_;
149 144 : }
150 0 : std::vector<FieldSharedPtr> arrayValue() const {
151 0 : checkType(Type::Array);
152 0 : return value_.array_value_;
153 0 : }
154 0 : bool booleanValue() const {
155 0 : checkType(Type::Boolean);
156 0 : return value_.boolean_value_;
157 0 : }
158 0 : double doubleValue() const {
159 0 : checkType(Type::Double);
160 0 : return value_.double_value_;
161 0 : }
162 0 : int64_t integerValue() const {
163 0 : checkType(Type::Integer);
164 0 : return value_.integer_value_;
165 0 : }
166 :
167 : nlohmann::json asJsonDocument() const;
168 : static void buildJsonDocument(const Field& field, nlohmann::json& value);
169 :
170 : uint64_t line_number_start_ = 0;
171 : uint64_t line_number_end_ = 0;
172 : const Type type_;
173 : Value value_;
174 : };
175 :
176 : /**
177 : * Consume events from SAX callbacks to build JSON Field.
178 : */
179 : class ObjectHandler : public nlohmann::json_sax<nlohmann::json> {
180 : public:
181 140 : ObjectHandler() = default;
182 :
183 : bool start_object(std::size_t) override;
184 : bool end_object() override;
185 : bool key(std::string& val) override;
186 : bool start_array(std::size_t) override;
187 : bool end_array() override;
188 190 : bool boolean(bool value) override { return handleValueEvent(Field::createValue(value)); }
189 0 : bool number_integer(int64_t value) override {
190 0 : return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
191 0 : }
192 712 : bool number_unsigned(uint64_t value) override {
193 712 : if (value > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
194 0 : throwExceptionOrPanic(
195 0 : Exception, fmt::format("JSON value from line {} is larger than int64_t (not supported)",
196 0 : line_number_));
197 0 : }
198 712 : return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
199 712 : }
200 0 : bool number_float(double value, const std::string&) override {
201 0 : return handleValueEvent(Field::createValue(value));
202 0 : }
203 0 : bool null() override { return handleValueEvent(Field::createNull()); }
204 31470 : bool string(std::string& value) override { return handleValueEvent(Field::createValue(value)); }
205 0 : bool binary(binary_t&) override { return false; }
206 : bool parse_error(std::size_t at, const std::string& token,
207 0 : const nlohmann::detail::exception& ex) override {
208 : // Parse errors are formatted like "[json.exception.parse_error.101] parse error: explanatory
209 : // string." or "[json.exception.parse_error.101] parser error at (position): explanatory
210 : // string.". All errors start with "[json.exception.<error_type>.<error_num]" see:
211 : // https://json.nlohmann.me/home/exceptions/#parse-errors
212 : // The `parse_error` method will be called also for non-parse errors.
213 0 : absl::string_view error = ex.what();
214 :
215 : // Colon will always exist in the parse error. For non-parse error use the
216 : // ending ']' as a separator.
217 0 : auto end = error.find(": ");
218 0 : auto prefix_end = error.find(']');
219 0 : if (end != std::string::npos) {
220 : // Extract portion after ": " to get error string.
221 0 : error_ = std::string(error.substr(end + 2));
222 : // Extract position information if present.
223 0 : auto start = error.find("at ");
224 0 : if (start != std::string::npos && (start + 3) < end) {
225 0 : start += 3;
226 0 : error_position_ = absl::StrCat(error.substr(start, end - start), ", token ", token);
227 0 : }
228 0 : } else if ((prefix_end != std::string::npos) && (absl::StartsWith(error, ErrorPrefix))) {
229 : // Non-parse error, fetching position from the arguments as it is not
230 : // present in the error string.
231 0 : error_position_ = absl::StrCat("position: ", at);
232 0 : error_ = std::string(error.substr(prefix_end + 1));
233 0 : } else {
234 0 : IS_ENVOY_BUG("Error string not present. Check nlohmann/json "
235 0 : "documentation in case error string changed.");
236 0 : }
237 0 : return false;
238 0 : }
239 :
240 140 : bool hasParseError() { return !error_.empty(); }
241 0 : std::string getParseError() { return error_; }
242 0 : std::string getErrorPosition() { return error_position_; }
243 :
244 140 : ObjectSharedPtr getRoot() { return root_; }
245 :
246 : int line_number_{1};
247 :
248 : private:
249 : bool handleValueEvent(FieldSharedPtr ptr);
250 :
251 : enum class State {
252 : ExpectRoot,
253 : ExpectKeyOrEndObject,
254 : ExpectValueOrStartObjectArray,
255 : ExpectArrayValueOrEndArray,
256 : ExpectFinished,
257 : };
258 : State state_{State::ExpectRoot};
259 :
260 : std::stack<FieldSharedPtr> stack_;
261 : std::string key_;
262 :
263 : FieldSharedPtr root_;
264 :
265 : std::string error_;
266 : std::string error_position_;
267 :
268 : static constexpr absl::string_view ErrorPrefix = "[json.exception.";
269 : };
270 :
271 : struct JsonContainer {
272 420 : JsonContainer(const char* ch, ObjectHandler* handler) : data(ch), handler_(handler) {}
273 : const char* data;
274 : ObjectHandler* handler_;
275 : };
276 :
277 : struct JsonIterator {
278 : using difference_type = std::ptrdiff_t; // NOLINT(readability-identifier-naming)
279 : using value_type = char; // NOLINT(readability-identifier-naming)
280 : using pointer = const char*; // NOLINT(readability-identifier-naming)
281 : using reference = const char&; // NOLINT(readability-identifier-naming)
282 : using iterator_category = std::input_iterator_tag; // NOLINT(readability-identifier-naming)
283 :
284 2278912 : JsonIterator& operator++() {
285 2278912 : ++ptr.data;
286 2278912 : return *this;
287 2278912 : }
288 :
289 2279052 : bool operator!=(const JsonIterator& rhs) const { return rhs.ptr.data != ptr.data; }
290 :
291 2278912 : reference operator*() {
292 2278912 : const char& ch = *(ptr.data);
293 2278912 : if (ch == '\n') {
294 82270 : ptr.handler_->line_number_++;
295 82270 : }
296 2278912 : return ch;
297 2278912 : }
298 :
299 : JsonContainer ptr;
300 : };
301 :
302 140 : JsonIterator begin(const JsonContainer& c) {
303 140 : return JsonIterator{JsonContainer(c.data, c.handler_)};
304 140 : }
305 :
306 140 : JsonIterator end(const JsonContainer& c) {
307 140 : return JsonIterator{JsonContainer(c.data + strlen(c.data), c.handler_)};
308 140 : }
309 :
310 0 : void Field::buildJsonDocument(const Field& field, nlohmann::json& value) {
311 0 : switch (field.type_) {
312 0 : case Type::Array: {
313 0 : for (const auto& element : field.value_.array_value_) {
314 0 : switch (element->type_) {
315 0 : case Type::Array:
316 0 : case Type::Object: {
317 0 : nlohmann::json nested_value;
318 0 : buildJsonDocument(*element, nested_value);
319 0 : value.push_back(nested_value);
320 0 : break;
321 0 : }
322 0 : case Type::Boolean:
323 0 : value.push_back(element->value_.boolean_value_);
324 0 : break;
325 0 : case Type::Double:
326 0 : value.push_back(element->value_.double_value_);
327 0 : break;
328 0 : case Type::Integer:
329 0 : value.push_back(element->value_.integer_value_);
330 0 : break;
331 0 : case Type::Null:
332 0 : value.push_back(nlohmann::json::value_t::null);
333 0 : break;
334 0 : case Type::String:
335 0 : value.push_back(element->value_.string_value_);
336 0 : }
337 0 : }
338 0 : break;
339 0 : }
340 0 : case Type::Object: {
341 0 : for (const auto& item : field.value_.object_value_) {
342 0 : auto name = std::string(item.first);
343 :
344 0 : switch (item.second->type_) {
345 0 : case Type::Array:
346 0 : case Type::Object: {
347 0 : nlohmann::json nested_value;
348 0 : buildJsonDocument(*item.second, nested_value);
349 0 : value.emplace(name, nested_value);
350 0 : break;
351 0 : }
352 0 : case Type::Boolean:
353 0 : value.emplace(name, item.second->value_.boolean_value_);
354 0 : break;
355 0 : case Type::Double:
356 0 : value.emplace(name, item.second->value_.double_value_);
357 0 : break;
358 0 : case Type::Integer:
359 0 : value.emplace(name, item.second->value_.integer_value_);
360 0 : break;
361 0 : case Type::Null:
362 0 : value.emplace(name, nlohmann::json::value_t::null);
363 0 : break;
364 0 : case Type::String:
365 0 : value.emplace(name, item.second->value_.string_value_);
366 0 : break;
367 0 : }
368 0 : }
369 0 : break;
370 0 : }
371 0 : case Type::Null: {
372 0 : break;
373 0 : }
374 0 : case Type::Boolean:
375 0 : FALLTHRU;
376 0 : case Type::Double:
377 0 : FALLTHRU;
378 0 : case Type::Integer:
379 0 : FALLTHRU;
380 0 : case Type::String:
381 0 : PANIC("not implemented");
382 0 : }
383 0 : }
384 :
385 0 : nlohmann::json Field::asJsonDocument() const {
386 0 : nlohmann::json j;
387 0 : buildJsonDocument(*this, j);
388 0 : return j;
389 0 : }
390 :
391 0 : uint64_t Field::hash() const { return HashUtil::xxHash64(asJsonString()); }
392 :
393 0 : absl::StatusOr<ValueType> Field::getValue(const std::string& name) const {
394 0 : auto value_itr = value_.object_value_.find(name);
395 0 : if (value_itr == value_.object_value_.end()) {
396 0 : return absl::NotFoundError(fmt::format("key '{}' missing from lines {}-{}", name,
397 0 : line_number_start_, line_number_end_));
398 0 : }
399 0 : switch (value_itr->second->type_) {
400 0 : case Type::Boolean:
401 0 : return value_itr->second->booleanValue();
402 0 : case Type::Double:
403 0 : return value_itr->second->doubleValue();
404 0 : case Type::Integer:
405 0 : return value_itr->second->integerValue();
406 0 : case Type::String:
407 0 : return value_itr->second->stringValue();
408 0 : default:
409 0 : return absl::InternalError(fmt::format("key '{}' not a value type from lines {}-{}", name,
410 0 : line_number_start_, line_number_end_));
411 0 : }
412 0 : }
413 :
414 0 : bool Field::getBoolean(const std::string& name) const {
415 0 : checkType(Type::Object);
416 0 : auto value_itr = value_.object_value_.find(name);
417 0 : if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Boolean)) {
418 0 : throwExceptionOrPanic(Exception,
419 0 : fmt::format("key '{}' missing or not a boolean from lines {}-{}", name,
420 0 : line_number_start_, line_number_end_));
421 0 : }
422 0 : return value_itr->second->booleanValue();
423 0 : }
424 :
425 0 : bool Field::getBoolean(const std::string& name, bool default_value) const {
426 0 : checkType(Type::Object);
427 0 : auto value_itr = value_.object_value_.find(name);
428 0 : if (value_itr != value_.object_value_.end()) {
429 0 : return getBoolean(name);
430 0 : }
431 0 : return default_value;
432 0 : }
433 :
434 0 : double Field::getDouble(const std::string& name) const {
435 0 : checkType(Type::Object);
436 0 : auto value_itr = value_.object_value_.find(name);
437 0 : if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Double)) {
438 0 : throwExceptionOrPanic(Exception,
439 0 : fmt::format("key '{}' missing or not a double from lines {}-{}", name,
440 0 : line_number_start_, line_number_end_));
441 0 : }
442 0 : return value_itr->second->doubleValue();
443 0 : }
444 :
445 0 : double Field::getDouble(const std::string& name, double default_value) const {
446 0 : checkType(Type::Object);
447 0 : auto value_itr = value_.object_value_.find(name);
448 0 : if (value_itr != value_.object_value_.end()) {
449 0 : return getDouble(name);
450 0 : }
451 0 : return default_value;
452 0 : }
453 :
454 0 : int64_t Field::getInteger(const std::string& name) const {
455 0 : checkType(Type::Object);
456 0 : auto value_itr = value_.object_value_.find(name);
457 0 : if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Integer)) {
458 0 : throwExceptionOrPanic(Exception,
459 0 : fmt::format("key '{}' missing or not an integer from lines {}-{}", name,
460 0 : line_number_start_, line_number_end_));
461 0 : }
462 0 : return value_itr->second->integerValue();
463 0 : }
464 :
465 0 : int64_t Field::getInteger(const std::string& name, int64_t default_value) const {
466 0 : checkType(Type::Object);
467 0 : auto value_itr = value_.object_value_.find(name);
468 0 : if (value_itr != value_.object_value_.end()) {
469 0 : return getInteger(name);
470 0 : }
471 0 : return default_value;
472 0 : }
473 :
474 0 : ObjectSharedPtr Field::getObject(const std::string& name, bool allow_empty) const {
475 0 : auto result = getObjectNoThrow(name, allow_empty);
476 0 : if (!result.ok()) {
477 0 : throwExceptionOrPanic(Exception, std::string(result.status().message()));
478 0 : }
479 :
480 0 : return result.value();
481 0 : }
482 :
483 : absl::StatusOr<ObjectSharedPtr> Field::getObjectNoThrow(const std::string& name,
484 0 : bool allow_empty) const {
485 0 : checkType(Type::Object);
486 0 : auto value_itr = value_.object_value_.find(name);
487 0 : if (value_itr == value_.object_value_.end()) {
488 0 : if (allow_empty) {
489 0 : return createObject();
490 0 : } else {
491 0 : return absl::NotFoundError(fmt::format("key '{}' missing from lines {}-{}", name,
492 0 : line_number_start_, line_number_end_));
493 0 : }
494 0 : } else if (!value_itr->second->isType(Type::Object)) {
495 0 : return absl::InternalError(fmt::format("key '{}' not an object from line {}", name,
496 0 : value_itr->second->line_number_start_));
497 0 : }
498 :
499 0 : return value_itr->second;
500 0 : }
501 :
502 : std::vector<ObjectSharedPtr> Field::getObjectArray(const std::string& name,
503 0 : bool allow_empty) const {
504 0 : checkType(Type::Object);
505 0 : auto value_itr = value_.object_value_.find(name);
506 0 : if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Array)) {
507 0 : if (allow_empty && value_itr == value_.object_value_.end()) {
508 0 : return {};
509 0 : }
510 0 : throwExceptionOrPanic(Exception,
511 0 : fmt::format("key '{}' missing or not an array from lines {}-{}", name,
512 0 : line_number_start_, line_number_end_));
513 0 : }
514 :
515 0 : std::vector<FieldSharedPtr> array_value = value_itr->second->arrayValue();
516 0 : return {array_value.begin(), array_value.end()};
517 0 : }
518 :
519 0 : std::string Field::getString(const std::string& name) const {
520 0 : checkType(Type::Object);
521 0 : auto value_itr = value_.object_value_.find(name);
522 0 : if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::String)) {
523 0 : throwExceptionOrPanic(Exception,
524 0 : fmt::format("key '{}' missing or not a string from lines {}-{}", name,
525 0 : line_number_start_, line_number_end_));
526 0 : }
527 0 : return value_itr->second->stringValue();
528 0 : }
529 :
530 0 : std::string Field::getString(const std::string& name, const std::string& default_value) const {
531 0 : checkType(Type::Object);
532 0 : auto value_itr = value_.object_value_.find(name);
533 0 : if (value_itr != value_.object_value_.end()) {
534 0 : return getString(name);
535 0 : }
536 0 : return default_value;
537 0 : }
538 :
539 0 : std::vector<std::string> Field::getStringArray(const std::string& name, bool allow_empty) const {
540 0 : checkType(Type::Object);
541 0 : std::vector<std::string> string_array;
542 0 : auto value_itr = value_.object_value_.find(name);
543 0 : if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Array)) {
544 0 : if (allow_empty && value_itr == value_.object_value_.end()) {
545 0 : return string_array;
546 0 : }
547 0 : throwExceptionOrPanic(Exception,
548 0 : fmt::format("key '{}' missing or not an array from lines {}-{}", name,
549 0 : line_number_start_, line_number_end_));
550 0 : }
551 :
552 0 : std::vector<FieldSharedPtr> array = value_itr->second->arrayValue();
553 0 : string_array.reserve(array.size());
554 0 : for (const auto& element : array) {
555 0 : if (!element->isType(Type::String)) {
556 0 : throwExceptionOrPanic(Exception,
557 0 : fmt::format("JSON array '{}' from line {} does not contain all strings",
558 0 : name, line_number_start_));
559 0 : }
560 0 : string_array.push_back(element->stringValue());
561 0 : }
562 :
563 0 : return string_array;
564 0 : }
565 :
566 7477 : std::vector<ObjectSharedPtr> Field::asObjectArray() const {
567 7477 : checkType(Type::Array);
568 7477 : return {value_.array_value_.begin(), value_.array_value_.end()};
569 7477 : }
570 :
571 0 : std::string Field::asJsonString() const {
572 0 : nlohmann::json j = asJsonDocument();
573 0 : return j.dump();
574 0 : }
575 :
576 0 : bool Field::empty() const {
577 0 : if (isType(Type::Object)) {
578 0 : return value_.object_value_.empty();
579 0 : } else if (isType(Type::Array)) {
580 0 : return value_.array_value_.empty();
581 0 : } else {
582 0 : throwExceptionOrPanic(
583 0 : Exception,
584 0 : fmt::format("Json does not support empty() on types other than array and object"));
585 0 : }
586 0 : }
587 :
588 0 : bool Field::hasObject(const std::string& name) const {
589 0 : checkType(Type::Object);
590 0 : auto value_itr = value_.object_value_.find(name);
591 0 : return value_itr != value_.object_value_.end();
592 0 : }
593 :
594 17890 : void Field::iterate(const ObjectCallback& callback) const {
595 17890 : checkType(Type::Object);
596 39672 : for (const auto& item : value_.object_value_) {
597 39672 : bool stop_iteration = !callback(item.first, *item.second);
598 39672 : if (stop_iteration) {
599 0 : break;
600 0 : }
601 39672 : }
602 17890 : }
603 :
604 0 : void Field::validateSchema(const std::string&) const {
605 0 : throwExceptionOrPanic(Exception, "not implemented");
606 0 : }
607 :
608 17890 : bool ObjectHandler::start_object(std::size_t) {
609 17890 : FieldSharedPtr object = Field::createObject();
610 17890 : object->setLineNumberStart(line_number_);
611 :
612 17890 : switch (state_) {
613 5431 : case State::ExpectValueOrStartObjectArray:
614 5431 : stack_.top()->insert(key_, object);
615 5431 : stack_.push(object);
616 5431 : state_ = State::ExpectKeyOrEndObject;
617 5431 : return true;
618 12361 : case State::ExpectArrayValueOrEndArray:
619 12361 : stack_.top()->append(object);
620 12361 : stack_.push(object);
621 12361 : state_ = State::ExpectKeyOrEndObject;
622 12361 : return true;
623 98 : case State::ExpectRoot:
624 98 : root_ = object;
625 98 : stack_.push(object);
626 98 : state_ = State::ExpectKeyOrEndObject;
627 98 : return true;
628 0 : case State::ExpectKeyOrEndObject:
629 0 : FALLTHRU;
630 0 : case State::ExpectFinished:
631 0 : PANIC("not implemented");
632 17890 : }
633 0 : return false;
634 17890 : }
635 :
636 17890 : bool ObjectHandler::end_object() {
637 17890 : if (state_ == State::ExpectKeyOrEndObject) {
638 17890 : stack_.top()->setLineNumberEnd(line_number_);
639 17890 : stack_.pop();
640 :
641 17890 : if (stack_.empty()) {
642 98 : state_ = State::ExpectFinished;
643 17792 : } else if (stack_.top()->isObject()) {
644 5431 : state_ = State::ExpectKeyOrEndObject;
645 12361 : } else if (stack_.top()->isArray()) {
646 12361 : state_ = State::ExpectArrayValueOrEndArray;
647 12361 : }
648 17890 : return true;
649 17890 : }
650 0 : PANIC("parsing error not handled");
651 0 : }
652 :
653 39672 : bool ObjectHandler::key(std::string& val) {
654 39672 : if (state_ == State::ExpectKeyOrEndObject) {
655 39672 : key_ = val;
656 39672 : state_ = State::ExpectValueOrStartObjectArray;
657 39672 : return true;
658 39672 : }
659 0 : PANIC("parsing error not handled");
660 0 : }
661 :
662 7329 : bool ObjectHandler::start_array(std::size_t) {
663 7329 : FieldSharedPtr array = Field::createArray();
664 7329 : array->setLineNumberStart(line_number_);
665 :
666 7329 : switch (state_) {
667 7287 : case State::ExpectValueOrStartObjectArray:
668 7287 : stack_.top()->insert(key_, array);
669 7287 : stack_.push(array);
670 7287 : state_ = State::ExpectArrayValueOrEndArray;
671 7287 : return true;
672 0 : case State::ExpectArrayValueOrEndArray:
673 0 : stack_.top()->append(array);
674 0 : stack_.push(array);
675 0 : return true;
676 42 : case State::ExpectRoot:
677 42 : root_ = array;
678 42 : stack_.push(array);
679 42 : state_ = State::ExpectArrayValueOrEndArray;
680 42 : return true;
681 0 : default:
682 0 : PANIC("parsing error not handled");
683 7329 : }
684 7329 : }
685 :
686 7329 : bool ObjectHandler::end_array() {
687 7329 : switch (state_) {
688 7329 : case State::ExpectArrayValueOrEndArray:
689 7329 : stack_.top()->setLineNumberEnd(line_number_);
690 7329 : stack_.pop();
691 :
692 7329 : if (stack_.empty()) {
693 42 : state_ = State::ExpectFinished;
694 7329 : } else if (stack_.top()->isObject()) {
695 7287 : state_ = State::ExpectKeyOrEndObject;
696 7287 : } else if (stack_.top()->isArray()) {
697 0 : state_ = State::ExpectArrayValueOrEndArray;
698 0 : }
699 :
700 7329 : return true;
701 0 : default:
702 0 : PANIC("parsing error not handled");
703 7329 : }
704 7329 : }
705 :
706 32372 : bool ObjectHandler::handleValueEvent(FieldSharedPtr ptr) {
707 32372 : ptr->setLineNumberStart(line_number_);
708 :
709 32372 : switch (state_) {
710 26954 : case State::ExpectValueOrStartObjectArray:
711 26954 : state_ = State::ExpectKeyOrEndObject;
712 26954 : stack_.top()->insert(key_, ptr);
713 26954 : return true;
714 5418 : case State::ExpectArrayValueOrEndArray:
715 5418 : stack_.top()->append(ptr);
716 5418 : return true;
717 0 : default:
718 0 : return true;
719 32372 : }
720 32372 : }
721 :
722 : } // namespace
723 :
724 140 : absl::StatusOr<ObjectSharedPtr> Factory::loadFromStringNoThrow(const std::string& json) {
725 140 : ObjectHandler handler;
726 140 : auto json_container = JsonContainer(json.c_str(), &handler);
727 :
728 140 : nlohmann::json::sax_parse(json_container, &handler);
729 :
730 140 : if (handler.hasParseError()) {
731 0 : return absl::InternalError(fmt::format("JSON supplied is not valid. Error({}): {}\n",
732 0 : handler.getErrorPosition(), handler.getParseError()));
733 0 : }
734 140 : return handler.getRoot();
735 140 : }
736 :
737 140 : ObjectSharedPtr Factory::loadFromString(const std::string& json) {
738 140 : auto result = loadFromStringNoThrow(json);
739 140 : if (!result.ok()) {
740 0 : throwExceptionOrPanic(Exception, std::string(result.status().message()));
741 0 : }
742 :
743 140 : return result.value();
744 140 : }
745 :
746 : FieldSharedPtr loadFromProtobufValueInternal(const ProtobufWkt::Value& protobuf_value);
747 : FieldSharedPtr loadFromProtobufStructInternal(const ProtobufWkt::Struct& protobuf_struct);
748 :
749 0 : FieldSharedPtr loadFromProtobufValueInternal(const ProtobufWkt::Value& protobuf_value) {
750 0 : switch (protobuf_value.kind_case()) {
751 0 : case ProtobufWkt::Value::kStringValue:
752 0 : return Field::createValue(protobuf_value.string_value());
753 0 : case ProtobufWkt::Value::kNumberValue:
754 0 : return Field::createValue(protobuf_value.number_value());
755 0 : case ProtobufWkt::Value::kBoolValue:
756 0 : return Field::createValue(protobuf_value.bool_value());
757 0 : case ProtobufWkt::Value::kNullValue:
758 0 : return Field::createNull();
759 0 : case ProtobufWkt::Value::kListValue: {
760 0 : FieldSharedPtr array = Field::createArray();
761 0 : for (const auto& list_value : protobuf_value.list_value().values()) {
762 0 : array->append(loadFromProtobufValueInternal(list_value));
763 0 : }
764 0 : return array;
765 0 : }
766 0 : case ProtobufWkt::Value::kStructValue:
767 0 : return loadFromProtobufStructInternal(protobuf_value.struct_value());
768 0 : default:
769 0 : throwExceptionOrPanic(Exception, "Protobuf value case not implemented");
770 0 : }
771 0 : }
772 :
773 0 : FieldSharedPtr loadFromProtobufStructInternal(const ProtobufWkt::Struct& protobuf_struct) {
774 0 : auto root = Field::createObject();
775 0 : for (const auto& field : protobuf_struct.fields()) {
776 0 : root->insert(field.first, loadFromProtobufValueInternal(field.second));
777 0 : }
778 :
779 0 : return root;
780 0 : }
781 :
782 0 : ObjectSharedPtr Factory::loadFromProtobufStruct(const ProtobufWkt::Struct& protobuf_struct) {
783 0 : return loadFromProtobufStructInternal(protobuf_struct);
784 0 : }
785 :
786 2934 : std::string Factory::serialize(absl::string_view str) {
787 2934 : nlohmann::json j(str);
788 2934 : return j.dump();
789 2934 : }
790 :
791 : } // namespace Nlohmann
792 : } // namespace Json
793 : } // namespace Envoy
|