Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/json/json_internal.cc
Line
Count
Source (jump to first uncovered line)
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
2.66M
  void setLineNumberStart(uint64_t line_number) { line_number_start_ = line_number; }
38
619k
  void setLineNumberEnd(uint64_t line_number) { line_number_end_ = line_number; }
39
40
  // Container factories for handler.
41
11.8k
  static FieldSharedPtr createObject() { return FieldSharedPtr{new Field(Type::Object)}; }
42
2.59M
  static FieldSharedPtr createArray() { return FieldSharedPtr{new Field(Type::Array)}; }
43
5
  static FieldSharedPtr createNull() { return FieldSharedPtr{new Field(Type::Null)}; }
44
45
614k
  bool isArray() const override { return type_ == Type::Array; }
46
617k
  bool isObject() const override { return type_ == Type::Object; }
47
48
  // Value factory.
49
79.0k
  template <typename T> static FieldSharedPtr createValue(T value) {
50
79.0k
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
79.0k
  }
json_internal.cc:std::__1::shared_ptr<Envoy::Json::Nlohmann::(anonymous namespace)::Field> Envoy::Json::Nlohmann::(anonymous namespace)::Field::createValue<bool>(bool)
Line
Count
Source
49
23
  template <typename T> static FieldSharedPtr createValue(T value) {
50
23
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
23
  }
json_internal.cc:std::__1::shared_ptr<Envoy::Json::Nlohmann::(anonymous namespace)::Field> Envoy::Json::Nlohmann::(anonymous namespace)::Field::createValue<long>(long)
Line
Count
Source
49
43.8k
  template <typename T> static FieldSharedPtr createValue(T value) {
50
43.8k
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
43.8k
  }
json_internal.cc:std::__1::shared_ptr<Envoy::Json::Nlohmann::(anonymous namespace)::Field> Envoy::Json::Nlohmann::(anonymous namespace)::Field::createValue<double>(double)
Line
Count
Source
49
28.2k
  template <typename T> static FieldSharedPtr createValue(T value) {
50
28.2k
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
28.2k
  }
json_internal.cc:std::__1::shared_ptr<Envoy::Json::Nlohmann::(anonymous namespace)::Field> Envoy::Json::Nlohmann::(anonymous namespace)::Field::createValue<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Line
Count
Source
49
6.98k
  template <typename T> static FieldSharedPtr createValue(T value) {
50
6.98k
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
6.98k
  }
52
53
2.65M
  void append(FieldSharedPtr field_ptr) {
54
2.65M
    checkType(Type::Array);
55
2.65M
    value_.array_value_.push_back(field_ptr);
56
2.65M
  }
57
18.7k
  void insert(const std::string& key, FieldSharedPtr field_ptr) {
58
18.7k
    checkType(Type::Object);
59
18.7k
    value_.object_value_[key] = field_ptr;
60
18.7k
  }
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
1.77k
  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
598
  static const char* typeAsString(Type t) {
99
598
    switch (t) {
100
5
    case Type::Array:
101
5
      return "Array";
102
4
    case Type::Boolean:
103
4
      return "Boolean";
104
96
    case Type::Double:
105
96
      return "Double";
106
192
    case Type::Integer:
107
192
      return "Integer";
108
1
    case Type::Null:
109
1
      return "Null";
110
1
    case Type::Object:
111
1
      return "Object";
112
299
    case Type::String:
113
299
      return "String";
114
598
    }
115
116
0
    return "";
117
598
  }
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
2.60M
  explicit Field(Type type) : type_(type) {}
129
6.98k
  explicit Field(const std::string& value) : type_(Type::String) { value_.string_value_ = value; }
130
43.8k
  explicit Field(int64_t value) : type_(Type::Integer) { value_.integer_value_ = value; }
131
28.2k
  explicit Field(double value) : type_(Type::Double) { value_.double_value_ = value; }
132
23
  explicit Field(bool value) : type_(Type::Boolean) { value_.boolean_value_ = value; }
133
134
2.68M
  bool isType(Type type) const { return type == type_; }
135
2.68M
  void checkType(Type type) const {
136
2.68M
    if (!isType(type)) {
137
299
      throwExceptionOrPanic(
138
299
          Exception,
139
299
          fmt::format(
140
299
              "JSON field from line {} accessed with type '{}' does not match actual type '{}'.",
141
299
              line_number_start_, typeAsString(type), typeAsString(type_)));
142
299
    }
143
2.68M
  }
144
145
  // Value return type functions.
146
1.77k
  std::string stringValue() const {
147
1.77k
    checkType(Type::String);
148
1.77k
    return value_.string_value_;
149
1.77k
  }
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
13.8k
  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
23
  bool boolean(bool value) override { return handleValueEvent(Field::createValue(value)); }
189
12.1k
  bool number_integer(int64_t value) override {
190
12.1k
    return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
191
12.1k
  }
192
31.7k
  bool number_unsigned(uint64_t value) override {
193
31.7k
    if (value > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
194
132
      throwExceptionOrPanic(
195
132
          Exception, fmt::format("JSON value from line {} is larger than int64_t (not supported)",
196
132
                                 line_number_));
197
132
    }
198
31.6k
    return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
199
31.7k
  }
200
22.6k
  bool number_float(double value, const std::string&) override {
201
22.6k
    return handleValueEvent(Field::createValue(value));
202
22.6k
  }
203
5
  bool null() override { return handleValueEvent(Field::createNull()); }
204
5.21k
  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
12.5k
                   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
12.5k
    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
12.5k
    auto end = error.find(": ");
218
12.5k
    auto prefix_end = error.find(']');
219
12.5k
    if (end != std::string::npos) {
220
      // Extract portion after ": " to get error string.
221
12.3k
      error_ = std::string(error.substr(end + 2));
222
      // Extract position information if present.
223
12.3k
      auto start = error.find("at ");
224
12.3k
      if (start != std::string::npos && (start + 3) < end) {
225
12.3k
        start += 3;
226
12.3k
        error_position_ = absl::StrCat(error.substr(start, end - start), ", token ", token);
227
12.3k
      }
228
12.3k
    } 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
258
      error_position_ = absl::StrCat("position: ", at);
232
258
      error_ = std::string(error.substr(prefix_end + 1));
233
258
    } else {
234
0
      IS_ENVOY_BUG("Error string not present. Check nlohmann/json "
235
0
                   "documentation in case error string changed.");
236
0
    }
237
12.5k
    return false;
238
12.5k
  }
239
240
13.6k
  bool hasParseError() { return !error_.empty(); }
241
12.5k
  std::string getParseError() { return error_; }
242
12.5k
  std::string getErrorPosition() { return error_position_; }
243
244
1.13k
  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
41.4k
  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
6.21M
  JsonIterator& operator++() {
285
6.21M
    ++ptr.data;
286
6.21M
    return *this;
287
6.21M
  }
288
289
6.21M
  bool operator!=(const JsonIterator& rhs) const { return rhs.ptr.data != ptr.data; }
290
291
6.21M
  reference operator*() {
292
6.21M
    const char& ch = *(ptr.data);
293
6.21M
    if (ch == '\n') {
294
58
      ptr.handler_->line_number_++;
295
58
    }
296
6.21M
    return ch;
297
6.21M
  }
298
299
  JsonContainer ptr;
300
};
301
302
13.8k
JsonIterator begin(const JsonContainer& c) {
303
13.8k
  return JsonIterator{JsonContainer(c.data, c.handler_)};
304
13.8k
}
305
306
13.8k
JsonIterator end(const JsonContainer& c) {
307
13.8k
  return JsonIterator{JsonContainer(c.data + strlen(c.data), c.handler_)};
308
13.8k
}
309
310
12.8k
void Field::buildJsonDocument(const Field& field, nlohmann::json& value) {
311
12.8k
  switch (field.type_) {
312
4.47k
  case Type::Array: {
313
9.06k
    for (const auto& element : field.value_.array_value_) {
314
9.06k
      switch (element->type_) {
315
2.69k
      case Type::Array:
316
3.73k
      case Type::Object: {
317
3.73k
        nlohmann::json nested_value;
318
3.73k
        buildJsonDocument(*element, nested_value);
319
3.73k
        value.push_back(nested_value);
320
3.73k
        break;
321
2.69k
      }
322
0
      case Type::Boolean:
323
0
        value.push_back(element->value_.boolean_value_);
324
0
        break;
325
4.77k
      case Type::Double:
326
4.77k
        value.push_back(element->value_.double_value_);
327
4.77k
        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
559
      case Type::String:
335
559
        value.push_back(element->value_.string_value_);
336
9.06k
      }
337
9.06k
    }
338
4.47k
    break;
339
4.47k
  }
340
8.41k
  case Type::Object: {
341
11.0k
    for (const auto& item : field.value_.object_value_) {
342
11.0k
      auto name = std::string(item.first);
343
344
11.0k
      switch (item.second->type_) {
345
1.78k
      case Type::Array:
346
9.07k
      case Type::Object: {
347
9.07k
        nlohmann::json nested_value;
348
9.07k
        buildJsonDocument(*item.second, nested_value);
349
9.07k
        value.emplace(name, nested_value);
350
9.07k
        break;
351
1.78k
      }
352
0
      case Type::Boolean:
353
0
        value.emplace(name, item.second->value_.boolean_value_);
354
0
        break;
355
769
      case Type::Double:
356
769
        value.emplace(name, item.second->value_.double_value_);
357
769
        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
1.21k
      case Type::String:
365
1.21k
        value.emplace(name, item.second->value_.string_value_);
366
1.21k
        break;
367
11.0k
      }
368
11.0k
    }
369
8.41k
    break;
370
8.41k
  }
371
8.41k
  case Type::Null: {
372
0
    break;
373
8.41k
  }
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
12.8k
  }
383
12.8k
}
384
385
74
nlohmann::json Field::asJsonDocument() const {
386
74
  nlohmann::json j;
387
74
  buildJsonDocument(*this, j);
388
74
  return j;
389
74
}
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
4.38k
std::vector<ObjectSharedPtr> Field::asObjectArray() const {
567
4.38k
  checkType(Type::Array);
568
4.38k
  return {value_.array_value_.begin(), value_.array_value_.end()};
569
4.38k
}
570
571
74
std::string Field::asJsonString() const {
572
74
  nlohmann::json j = asJsonDocument();
573
  // Call with defaults except in the case of UTF-8 errors which we replace
574
  // invalid UTF-8 characters instead of throwing an exception.
575
74
  return j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
576
74
}
577
578
0
bool Field::empty() const {
579
0
  if (isType(Type::Object)) {
580
0
    return value_.object_value_.empty();
581
0
  } else if (isType(Type::Array)) {
582
0
    return value_.array_value_.empty();
583
0
  } else {
584
0
    throwExceptionOrPanic(
585
0
        Exception,
586
0
        fmt::format("Json does not support empty() on types other than array and object"));
587
0
  }
588
0
}
589
590
0
bool Field::hasObject(const std::string& name) const {
591
0
  checkType(Type::Object);
592
0
  auto value_itr = value_.object_value_.find(name);
593
0
  return value_itr != value_.object_value_.end();
594
0
}
595
596
0
void Field::iterate(const ObjectCallback& callback) const {
597
0
  checkType(Type::Object);
598
0
  for (const auto& item : value_.object_value_) {
599
0
    bool stop_iteration = !callback(item.first, *item.second);
600
0
    if (stop_iteration) {
601
0
      break;
602
0
    }
603
0
  }
604
0
}
605
606
0
void Field::validateSchema(const std::string&) const {
607
0
  throwExceptionOrPanic(Exception, "not implemented");
608
0
}
609
610
3.40k
bool ObjectHandler::start_object(std::size_t) {
611
3.40k
  FieldSharedPtr object = Field::createObject();
612
3.40k
  object->setLineNumberStart(line_number_);
613
614
3.40k
  switch (state_) {
615
2.01k
  case State::ExpectValueOrStartObjectArray:
616
2.01k
    stack_.top()->insert(key_, object);
617
2.01k
    stack_.push(object);
618
2.01k
    state_ = State::ExpectKeyOrEndObject;
619
2.01k
    return true;
620
1.39k
  case State::ExpectArrayValueOrEndArray:
621
1.39k
    stack_.top()->append(object);
622
1.39k
    stack_.push(object);
623
1.39k
    state_ = State::ExpectKeyOrEndObject;
624
1.39k
    return true;
625
0
  case State::ExpectRoot:
626
0
    root_ = object;
627
0
    stack_.push(object);
628
0
    state_ = State::ExpectKeyOrEndObject;
629
0
    return true;
630
0
  case State::ExpectKeyOrEndObject:
631
0
    FALLTHRU;
632
0
  case State::ExpectFinished:
633
0
    PANIC("not implemented");
634
3.40k
  }
635
0
  return false;
636
3.40k
}
637
638
97
bool ObjectHandler::end_object() {
639
97
  if (state_ == State::ExpectKeyOrEndObject) {
640
97
    stack_.top()->setLineNumberEnd(line_number_);
641
97
    stack_.pop();
642
643
97
    if (stack_.empty()) {
644
0
      state_ = State::ExpectFinished;
645
97
    } else if (stack_.top()->isObject()) {
646
68
      state_ = State::ExpectKeyOrEndObject;
647
68
    } else if (stack_.top()->isArray()) {
648
29
      state_ = State::ExpectArrayValueOrEndArray;
649
29
    }
650
97
    return true;
651
97
  }
652
0
  PANIC("parsing error not handled");
653
0
}
654
655
7.79k
bool ObjectHandler::key(std::string& val) {
656
7.79k
  if (state_ == State::ExpectKeyOrEndObject) {
657
7.79k
    key_ = val;
658
7.79k
    state_ = State::ExpectValueOrStartObjectArray;
659
7.79k
    return true;
660
7.79k
  }
661
0
  PANIC("parsing error not handled");
662
0
}
663
664
2.59M
bool ObjectHandler::start_array(std::size_t) {
665
2.59M
  FieldSharedPtr array = Field::createArray();
666
2.59M
  array->setLineNumberStart(line_number_);
667
668
2.59M
  switch (state_) {
669
2.91k
  case State::ExpectValueOrStartObjectArray:
670
2.91k
    stack_.top()->insert(key_, array);
671
2.91k
    stack_.push(array);
672
2.91k
    state_ = State::ExpectArrayValueOrEndArray;
673
2.91k
    return true;
674
2.57M
  case State::ExpectArrayValueOrEndArray:
675
2.57M
    stack_.top()->append(array);
676
2.57M
    stack_.push(array);
677
2.57M
    return true;
678
13.8k
  case State::ExpectRoot:
679
13.8k
    root_ = array;
680
13.8k
    stack_.push(array);
681
13.8k
    state_ = State::ExpectArrayValueOrEndArray;
682
13.8k
    return true;
683
0
  default:
684
0
    PANIC("parsing error not handled");
685
2.59M
  }
686
2.59M
}
687
688
619k
bool ObjectHandler::end_array() {
689
619k
  switch (state_) {
690
619k
  case State::ExpectArrayValueOrEndArray:
691
619k
    stack_.top()->setLineNumberEnd(line_number_);
692
619k
    stack_.pop();
693
694
619k
    if (stack_.empty()) {
695
2.01k
      state_ = State::ExpectFinished;
696
617k
    } else if (stack_.top()->isObject()) {
697
2.52k
      state_ = State::ExpectKeyOrEndObject;
698
614k
    } else if (stack_.top()->isArray()) {
699
614k
      state_ = State::ExpectArrayValueOrEndArray;
700
614k
    }
701
702
619k
    return true;
703
0
  default:
704
0
    PANIC("parsing error not handled");
705
619k
  }
706
619k
}
707
708
71.7k
bool ObjectHandler::handleValueEvent(FieldSharedPtr ptr) {
709
71.7k
  ptr->setLineNumberStart(line_number_);
710
711
71.7k
  switch (state_) {
712
2.73k
  case State::ExpectValueOrStartObjectArray:
713
2.73k
    state_ = State::ExpectKeyOrEndObject;
714
2.73k
    stack_.top()->insert(key_, ptr);
715
2.73k
    return true;
716
69.0k
  case State::ExpectArrayValueOrEndArray:
717
69.0k
    stack_.top()->append(ptr);
718
69.0k
    return true;
719
0
  default:
720
0
    return true;
721
71.7k
  }
722
71.7k
}
723
724
} // namespace
725
726
13.8k
absl::StatusOr<ObjectSharedPtr> Factory::loadFromStringNoThrow(const std::string& json) {
727
13.8k
  ObjectHandler handler;
728
13.8k
  auto json_container = JsonContainer(json.c_str(), &handler);
729
730
13.8k
  nlohmann::json::sax_parse(json_container, &handler);
731
732
13.8k
  if (handler.hasParseError()) {
733
12.5k
    return absl::InternalError(fmt::format("JSON supplied is not valid. Error({}): {}\n",
734
12.5k
                                           handler.getErrorPosition(), handler.getParseError()));
735
12.5k
  }
736
1.26k
  return handler.getRoot();
737
13.8k
}
738
739
13.8k
ObjectSharedPtr Factory::loadFromString(const std::string& json) {
740
13.8k
  auto result = loadFromStringNoThrow(json);
741
13.8k
  if (!result.ok()) {
742
12.5k
    throwExceptionOrPanic(Exception, std::string(result.status().message()));
743
12.5k
  }
744
745
1.26k
  return result.value();
746
13.8k
}
747
748
FieldSharedPtr loadFromProtobufValueInternal(const ProtobufWkt::Value& protobuf_value);
749
FieldSharedPtr loadFromProtobufStructInternal(const ProtobufWkt::Struct& protobuf_struct);
750
751
20.1k
FieldSharedPtr loadFromProtobufValueInternal(const ProtobufWkt::Value& protobuf_value) {
752
20.1k
  switch (protobuf_value.kind_case()) {
753
1.77k
  case ProtobufWkt::Value::kStringValue:
754
1.77k
    return Field::createValue(protobuf_value.string_value());
755
5.54k
  case ProtobufWkt::Value::kNumberValue:
756
5.54k
    return Field::createValue(protobuf_value.number_value());
757
0
  case ProtobufWkt::Value::kBoolValue:
758
0
    return Field::createValue(protobuf_value.bool_value());
759
0
  case ProtobufWkt::Value::kNullValue:
760
0
    return Field::createNull();
761
4.47k
  case ProtobufWkt::Value::kListValue: {
762
4.47k
    FieldSharedPtr array = Field::createArray();
763
9.06k
    for (const auto& list_value : protobuf_value.list_value().values()) {
764
9.06k
      array->append(loadFromProtobufValueInternal(list_value));
765
9.06k
    }
766
4.47k
    return array;
767
0
  }
768
8.33k
  case ProtobufWkt::Value::kStructValue:
769
8.33k
    return loadFromProtobufStructInternal(protobuf_value.struct_value());
770
0
  default:
771
0
    throwExceptionOrPanic(Exception, "Protobuf value case not implemented");
772
20.1k
  }
773
20.1k
}
774
775
8.41k
FieldSharedPtr loadFromProtobufStructInternal(const ProtobufWkt::Struct& protobuf_struct) {
776
8.41k
  auto root = Field::createObject();
777
11.0k
  for (const auto& field : protobuf_struct.fields()) {
778
11.0k
    root->insert(field.first, loadFromProtobufValueInternal(field.second));
779
11.0k
  }
780
781
8.41k
  return root;
782
8.41k
}
783
784
74
ObjectSharedPtr Factory::loadFromProtobufStruct(const ProtobufWkt::Struct& protobuf_struct) {
785
74
  return loadFromProtobufStructInternal(protobuf_struct);
786
74
}
787
788
2.77k
std::string Factory::serialize(absl::string_view str) {
789
2.77k
  nlohmann::json j(str);
790
2.77k
  return j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
791
2.77k
}
792
793
0
std::vector<uint8_t> Factory::jsonToMsgpack(const std::string& json_string) {
794
0
  return nlohmann::json::to_msgpack(nlohmann::json::parse(json_string, nullptr, false));
795
0
}
796
797
} // namespace Nlohmann
798
} // namespace Json
799
} // namespace Envoy