Coverage Report

Created: 2023-11-12 09:30

/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
4.64M
  void setLineNumberStart(uint64_t line_number) { line_number_start_ = line_number; }
38
942k
  void setLineNumberEnd(uint64_t line_number) { line_number_end_ = line_number; }
39
40
  // Container factories for handler.
41
541k
  static FieldSharedPtr createObject() { return FieldSharedPtr{new Field(Type::Object)}; }
42
1.95M
  static FieldSharedPtr createArray() { return FieldSharedPtr{new Field(Type::Array)}; }
43
64
  static FieldSharedPtr createNull() { return FieldSharedPtr{new Field(Type::Null)}; }
44
45
1.65M
  bool isArray() const override { return type_ == Type::Array; }
46
2.52M
  bool isObject() const override { return type_ == Type::Object; }
47
48
  // Value factory.
49
2.18M
  template <typename T> static FieldSharedPtr createValue(T value) {
50
2.18M
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
2.18M
  }
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
5.71k
  template <typename T> static FieldSharedPtr createValue(T value) {
50
5.71k
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
5.71k
  }
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
729k
  template <typename T> static FieldSharedPtr createValue(T value) {
50
729k
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
729k
  }
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
478k
  template <typename T> static FieldSharedPtr createValue(T value) {
50
478k
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
478k
  }
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
969k
  template <typename T> static FieldSharedPtr createValue(T value) {
50
969k
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
51
969k
  }
52
53
3.39M
  void append(FieldSharedPtr field_ptr) {
54
3.39M
    checkType(Type::Array);
55
3.39M
    value_.array_value_.push_back(field_ptr);
56
3.39M
  }
57
1.23M
  void insert(const std::string& key, FieldSharedPtr field_ptr) {
58
1.23M
    checkType(Type::Object);
59
1.23M
    value_.object_value_[key] = field_ptr;
60
1.23M
  }
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
14.9k
  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
7.89k
  static const char* typeAsString(Type t) {
99
7.89k
    switch (t) {
100
11
    case Type::Array:
101
11
      return "Array";
102
25
    case Type::Boolean:
103
25
      return "Boolean";
104
258
    case Type::Double:
105
258
      return "Double";
106
3.60k
    case Type::Integer:
107
3.60k
      return "Integer";
108
16
    case Type::Null:
109
16
      return "Null";
110
34
    case Type::Object:
111
34
      return "Object";
112
3.94k
    case Type::String:
113
3.94k
      return "String";
114
7.89k
    }
115
116
0
    return "";
117
7.89k
  }
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.49M
  explicit Field(Type type) : type_(type) {}
129
969k
  explicit Field(const std::string& value) : type_(Type::String) { value_.string_value_ = value; }
130
729k
  explicit Field(int64_t value) : type_(Type::Integer) { value_.integer_value_ = value; }
131
478k
  explicit Field(double value) : type_(Type::Double) { value_.double_value_ = value; }
132
5.71k
  explicit Field(bool value) : type_(Type::Boolean) { value_.boolean_value_ = value; }
133
134
5.37M
  bool isType(Type type) const { return type == type_; }
135
5.37M
  void checkType(Type type) const {
136
5.37M
    if (!isType(type)) {
137
3.94k
      throwExceptionOrPanic(
138
3.94k
          Exception,
139
3.94k
          fmt::format(
140
3.94k
              "JSON field from line {} accessed with type '{}' does not match actual type '{}'.",
141
3.94k
              line_number_start_, typeAsString(type), typeAsString(type_)));
142
3.94k
    }
143
5.37M
  }
144
145
  // Value return type functions.
146
14.9k
  std::string stringValue() const {
147
14.9k
    checkType(Type::String);
148
14.9k
    return value_.string_value_;
149
14.9k
  }
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
51.5k
  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
5.71k
  bool boolean(bool value) override { return handleValueEvent(Field::createValue(value)); }
189
238k
  bool number_integer(int64_t value) override {
190
238k
    return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
191
238k
  }
192
490k
  bool number_unsigned(uint64_t value) override {
193
490k
    if (value > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
194
502
      throwExceptionOrPanic(
195
502
          Exception, fmt::format("JSON value from line {} is larger than int64_t (not supported)",
196
502
                                 line_number_));
197
502
    }
198
490k
    return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
199
490k
  }
200
472k
  bool number_float(double value, const std::string&) override {
201
472k
    return handleValueEvent(Field::createValue(value));
202
472k
  }
203
64
  bool null() override { return handleValueEvent(Field::createNull()); }
204
962k
  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
39.6k
                   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
39.6k
    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
39.6k
    auto end = error.find(": ");
218
39.6k
    auto prefix_end = error.find(']');
219
39.6k
    if (end != std::string::npos) {
220
      // Extract portion after ": " to get error string.
221
38.1k
      error_ = std::string(error.substr(end + 2));
222
      // Extract position information if present.
223
38.1k
      auto start = error.find("at ");
224
38.1k
      if (start != std::string::npos && (start + 3) < end) {
225
38.1k
        start += 3;
226
38.1k
        error_position_ = absl::StrCat(error.substr(start, end - start), ", token ", token);
227
38.1k
      }
228
38.1k
    } 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
1.51k
      error_position_ = absl::StrCat("position: ", at);
232
1.51k
      error_ = std::string(error.substr(prefix_end + 1));
233
1.51k
    } else {
234
0
      IS_ENVOY_BUG("Error string not present. Check nlohmann/json "
235
0
                   "documentation in case error string changed.");
236
0
    }
237
39.6k
    return false;
238
39.6k
  }
239
240
51.0k
  bool hasParseError() { return !error_.empty(); }
241
39.6k
  std::string getParseError() { return error_; }
242
39.6k
  std::string getErrorPosition() { return error_position_; }
243
244
11.4k
  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
154k
  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
78.2M
  JsonIterator& operator++() {
285
78.2M
    ++ptr.data;
286
78.2M
    return *this;
287
78.2M
  }
288
289
78.3M
  bool operator!=(const JsonIterator& rhs) const { return rhs.ptr.data != ptr.data; }
290
291
78.2M
  reference operator*() {
292
78.2M
    const char& ch = *(ptr.data);
293
78.2M
    if (ch == '\n') {
294
2.30M
      ptr.handler_->line_number_++;
295
2.30M
    }
296
78.2M
    return ch;
297
78.2M
  }
298
299
  JsonContainer ptr;
300
};
301
302
51.5k
JsonIterator begin(const JsonContainer& c) {
303
51.5k
  return JsonIterator{JsonContainer(c.data, c.handler_)};
304
51.5k
}
305
306
51.5k
JsonIterator end(const JsonContainer& c) {
307
51.5k
  return JsonIterator{JsonContainer(c.data + strlen(c.data), c.handler_)};
308
51.5k
}
309
310
23.4k
void Field::buildJsonDocument(const Field& field, nlohmann::json& value) {
311
23.4k
  switch (field.type_) {
312
7.37k
  case Type::Array: {
313
18.2k
    for (const auto& element : field.value_.array_value_) {
314
18.2k
      switch (element->type_) {
315
4.99k
      case Type::Array:
316
7.70k
      case Type::Object: {
317
7.70k
        nlohmann::json nested_value;
318
7.70k
        buildJsonDocument(*element, nested_value);
319
7.70k
        value.push_back(nested_value);
320
7.70k
        break;
321
4.99k
      }
322
0
      case Type::Boolean:
323
0
        value.push_back(element->value_.boolean_value_);
324
0
        break;
325
4.10k
      case Type::Double:
326
4.10k
        value.push_back(element->value_.double_value_);
327
4.10k
        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
6.46k
      case Type::String:
335
6.46k
        value.push_back(element->value_.string_value_);
336
18.2k
      }
337
18.2k
    }
338
7.37k
    break;
339
7.37k
  }
340
16.1k
  case Type::Object: {
341
18.5k
    for (const auto& item : field.value_.object_value_) {
342
18.5k
      auto name = std::string(item.first);
343
344
18.5k
      switch (item.second->type_) {
345
2.38k
      case Type::Array:
346
15.6k
      case Type::Object: {
347
15.6k
        nlohmann::json nested_value;
348
15.6k
        buildJsonDocument(*item.second, nested_value);
349
15.6k
        value.emplace(name, nested_value);
350
15.6k
        break;
351
2.38k
      }
352
0
      case Type::Boolean:
353
0
        value.emplace(name, item.second->value_.boolean_value_);
354
0
        break;
355
1.65k
      case Type::Double:
356
1.65k
        value.emplace(name, item.second->value_.double_value_);
357
1.65k
        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.22k
      case Type::String:
365
1.22k
        value.emplace(name, item.second->value_.string_value_);
366
1.22k
        break;
367
18.5k
      }
368
18.5k
    }
369
16.1k
    break;
370
16.1k
  }
371
16.1k
  case Type::Null: {
372
0
    break;
373
16.1k
  }
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
23.4k
  }
383
23.4k
}
384
385
123
nlohmann::json Field::asJsonDocument() const {
386
123
  nlohmann::json j;
387
123
  buildJsonDocument(*this, j);
388
123
  return j;
389
123
}
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
233k
std::vector<ObjectSharedPtr> Field::asObjectArray() const {
567
233k
  checkType(Type::Array);
568
233k
  return {value_.array_value_.begin(), value_.array_value_.end()};
569
233k
}
570
571
123
std::string Field::asJsonString() const {
572
123
  nlohmann::json j = asJsonDocument();
573
123
  return j.dump();
574
123
}
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
503k
void Field::iterate(const ObjectCallback& callback) const {
595
503k
  checkType(Type::Object);
596
1.11M
  for (const auto& item : value_.object_value_) {
597
1.11M
    bool stop_iteration = !callback(item.first, *item.second);
598
1.11M
    if (stop_iteration) {
599
0
      break;
600
0
    }
601
1.11M
  }
602
503k
}
603
604
0
void Field::validateSchema(const std::string&) const {
605
0
  throwExceptionOrPanic(Exception, "not implemented");
606
0
}
607
608
525k
bool ObjectHandler::start_object(std::size_t) {
609
525k
  FieldSharedPtr object = Field::createObject();
610
525k
  object->setLineNumberStart(line_number_);
611
612
525k
  switch (state_) {
613
173k
  case State::ExpectValueOrStartObjectArray:
614
173k
    stack_.top()->insert(key_, object);
615
173k
    stack_.push(object);
616
173k
    state_ = State::ExpectKeyOrEndObject;
617
173k
    return true;
618
348k
  case State::ExpectArrayValueOrEndArray:
619
348k
    stack_.top()->append(object);
620
348k
    stack_.push(object);
621
348k
    state_ = State::ExpectKeyOrEndObject;
622
348k
    return true;
623
2.64k
  case State::ExpectRoot:
624
2.64k
    root_ = object;
625
2.64k
    stack_.push(object);
626
2.64k
    state_ = State::ExpectKeyOrEndObject;
627
2.64k
    return true;
628
0
  case State::ExpectKeyOrEndObject:
629
0
    FALLTHRU;
630
0
  case State::ExpectFinished:
631
0
    PANIC("not implemented");
632
525k
  }
633
0
  return false;
634
525k
}
635
636
505k
bool ObjectHandler::end_object() {
637
505k
  if (state_ == State::ExpectKeyOrEndObject) {
638
505k
    stack_.top()->setLineNumberEnd(line_number_);
639
505k
    stack_.pop();
640
641
505k
    if (stack_.empty()) {
642
2.64k
      state_ = State::ExpectFinished;
643
502k
    } else if (stack_.top()->isObject()) {
644
161k
      state_ = State::ExpectKeyOrEndObject;
645
341k
    } else if (stack_.top()->isArray()) {
646
341k
      state_ = State::ExpectArrayValueOrEndArray;
647
341k
    }
648
505k
    return true;
649
505k
  }
650
0
  PANIC("parsing error not handled");
651
0
}
652
653
1.21M
bool ObjectHandler::key(std::string& val) {
654
1.21M
  if (state_ == State::ExpectKeyOrEndObject) {
655
1.21M
    key_ = val;
656
1.21M
    state_ = State::ExpectValueOrStartObjectArray;
657
1.21M
    return true;
658
1.21M
  }
659
0
  PANIC("parsing error not handled");
660
0
}
661
662
1.94M
bool ObjectHandler::start_array(std::size_t) {
663
1.94M
  FieldSharedPtr array = Field::createArray();
664
1.94M
  array->setLineNumberStart(line_number_);
665
666
1.94M
  switch (state_) {
667
210k
  case State::ExpectValueOrStartObjectArray:
668
210k
    stack_.top()->insert(key_, array);
669
210k
    stack_.push(array);
670
210k
    state_ = State::ExpectArrayValueOrEndArray;
671
210k
    return true;
672
1.68M
  case State::ExpectArrayValueOrEndArray:
673
1.68M
    stack_.top()->append(array);
674
1.68M
    stack_.push(array);
675
1.68M
    return true;
676
48.9k
  case State::ExpectRoot:
677
48.9k
    root_ = array;
678
48.9k
    stack_.push(array);
679
48.9k
    state_ = State::ExpectArrayValueOrEndArray;
680
48.9k
    return true;
681
0
  default:
682
0
    PANIC("parsing error not handled");
683
1.94M
  }
684
1.94M
}
685
686
437k
bool ObjectHandler::end_array() {
687
437k
  switch (state_) {
688
437k
  case State::ExpectArrayValueOrEndArray:
689
437k
    stack_.top()->setLineNumberEnd(line_number_);
690
437k
    stack_.pop();
691
692
437k
    if (stack_.empty()) {
693
9.98k
      state_ = State::ExpectFinished;
694
427k
    } else if (stack_.top()->isObject()) {
695
209k
      state_ = State::ExpectKeyOrEndObject;
696
217k
    } else if (stack_.top()->isArray()) {
697
217k
      state_ = State::ExpectArrayValueOrEndArray;
698
217k
    }
699
700
437k
    return true;
701
0
  default:
702
0
    PANIC("parsing error not handled");
703
437k
  }
704
437k
}
705
706
2.16M
bool ObjectHandler::handleValueEvent(FieldSharedPtr ptr) {
707
2.16M
  ptr->setLineNumberStart(line_number_);
708
709
2.16M
  switch (state_) {
710
831k
  case State::ExpectValueOrStartObjectArray:
711
831k
    state_ = State::ExpectKeyOrEndObject;
712
831k
    stack_.top()->insert(key_, ptr);
713
831k
    return true;
714
1.33M
  case State::ExpectArrayValueOrEndArray:
715
1.33M
    stack_.top()->append(ptr);
716
1.33M
    return true;
717
0
  default:
718
0
    return true;
719
2.16M
  }
720
2.16M
}
721
722
} // namespace
723
724
51.5k
absl::StatusOr<ObjectSharedPtr> Factory::loadFromStringNoThrow(const std::string& json) {
725
51.5k
  ObjectHandler handler;
726
51.5k
  auto json_container = JsonContainer(json.c_str(), &handler);
727
728
51.5k
  nlohmann::json::sax_parse(json_container, &handler);
729
730
51.5k
  if (handler.hasParseError()) {
731
39.6k
    return absl::InternalError(fmt::format("JSON supplied is not valid. Error({}): {}\n",
732
39.6k
                                           handler.getErrorPosition(), handler.getParseError()));
733
39.6k
  }
734
11.9k
  return handler.getRoot();
735
51.5k
}
736
737
51.5k
ObjectSharedPtr Factory::loadFromString(const std::string& json) {
738
51.5k
  auto result = loadFromStringNoThrow(json);
739
51.5k
  if (!result.ok()) {
740
39.6k
    throwExceptionOrPanic(Exception, std::string(result.status().message()));
741
39.6k
  }
742
743
11.9k
  return result.value();
744
51.5k
}
745
746
FieldSharedPtr loadFromProtobufValueInternal(const ProtobufWkt::Value& protobuf_value);
747
FieldSharedPtr loadFromProtobufStructInternal(const ProtobufWkt::Struct& protobuf_struct);
748
749
36.7k
FieldSharedPtr loadFromProtobufValueInternal(const ProtobufWkt::Value& protobuf_value) {
750
36.7k
  switch (protobuf_value.kind_case()) {
751
7.68k
  case ProtobufWkt::Value::kStringValue:
752
7.68k
    return Field::createValue(protobuf_value.string_value());
753
5.75k
  case ProtobufWkt::Value::kNumberValue:
754
5.75k
    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
7.37k
  case ProtobufWkt::Value::kListValue: {
760
7.37k
    FieldSharedPtr array = Field::createArray();
761
18.2k
    for (const auto& list_value : protobuf_value.list_value().values()) {
762
18.2k
      array->append(loadFromProtobufValueInternal(list_value));
763
18.2k
    }
764
7.37k
    return array;
765
0
  }
766
15.9k
  case ProtobufWkt::Value::kStructValue:
767
15.9k
    return loadFromProtobufStructInternal(protobuf_value.struct_value());
768
0
  default:
769
0
    throwExceptionOrPanic(Exception, "Protobuf value case not implemented");
770
36.7k
  }
771
36.7k
}
772
773
16.1k
FieldSharedPtr loadFromProtobufStructInternal(const ProtobufWkt::Struct& protobuf_struct) {
774
16.1k
  auto root = Field::createObject();
775
18.5k
  for (const auto& field : protobuf_struct.fields()) {
776
18.5k
    root->insert(field.first, loadFromProtobufValueInternal(field.second));
777
18.5k
  }
778
779
16.1k
  return root;
780
16.1k
}
781
782
123
ObjectSharedPtr Factory::loadFromProtobufStruct(const ProtobufWkt::Struct& protobuf_struct) {
783
123
  return loadFromProtobufStructInternal(protobuf_struct);
784
123
}
785
786
3.35k
std::string Factory::serialize(absl::string_view str) {
787
3.35k
  nlohmann::json j(str);
788
3.35k
  return j.dump();
789
3.35k
}
790
791
} // namespace Nlohmann
792
} // namespace Json
793
} // namespace Envoy