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 "absl/strings/match.h"
20
#include "include/nlohmann/json.hpp"
21

            
22
namespace Envoy {
23
namespace Json {
24
namespace Nlohmann {
25

            
26
namespace {
27

            
28
/**
29
 * Internal representation of Object.
30
 */
31
class Field;
32
using FieldSharedPtr = std::shared_ptr<Field>;
33

            
34
class Field : public Object {
35
public:
36
44237
  void setLineNumberStart(uint64_t line_number) { line_number_start_ = line_number; }
37
17065
  void setLineNumberEnd(uint64_t line_number) { line_number_end_ = line_number; }
38

            
39
  // Container factories for handler.
40
12678
  static FieldSharedPtr createObject() { return FieldSharedPtr{new Field(Type::Object)}; }
41
4499
  static FieldSharedPtr createArray() { return FieldSharedPtr{new Field(Type::Array)}; }
42
1086
  static FieldSharedPtr createNull() { return FieldSharedPtr{new Field(Type::Null)}; }
43

            
44
9392
  bool isArray() const override { return type_ == Type::Array; }
45
18321
  bool isObject() const override { return type_ == Type::Object; }
46

            
47
  // Value factory.
48
26192
  template <typename T> static FieldSharedPtr createValue(T value) {
49
26192
    return FieldSharedPtr{new Field(value)}; // NOLINT(modernize-make-shared)
50
26192
  }
51

            
52
12339
  absl::Status append(FieldSharedPtr field_ptr) {
53
12339
    RETURN_IF_NOT_OK(checkType(Type::Array));
54
12339
    value_.array_value_.push_back(field_ptr);
55
12339
    return absl::OkStatus();
56
12339
  }
57
31139
  absl::Status insert(const std::string& key, FieldSharedPtr field_ptr) {
58
31139
    RETURN_IF_NOT_OK(checkType(Type::Object));
59
31139
    value_.object_value_[key] = field_ptr;
60
31139
    return absl::OkStatus();
61
31139
  }
62

            
63
  uint64_t hash() const override;
64

            
65
  absl::StatusOr<ValueType> getValue(const std::string& name) const override;
66
  absl::StatusOr<bool> getBoolean(const std::string& name) const override;
67
  absl::StatusOr<bool> getBoolean(const std::string& name, bool default_value) const override;
68
  absl::StatusOr<double> getDouble(const std::string& name) const override;
69
  absl::StatusOr<double> getDouble(const std::string& name, double default_value) const override;
70
  absl::StatusOr<int64_t> getInteger(const std::string& name) const override;
71
  absl::StatusOr<int64_t> getInteger(const std::string& name, int64_t default_value) const override;
72
  absl::StatusOr<ObjectSharedPtr> getObject(const std::string& name,
73
                                            bool allow_empty) const override;
74
  absl::StatusOr<std::vector<ObjectSharedPtr>> getObjectArray(const std::string& name,
75
                                                              bool allow_empty) const override;
76
  absl::StatusOr<std::string> getString(const std::string& name) const override;
77
  absl::StatusOr<std::string> getString(const std::string& name,
78
                                        const std::string& default_value) const override;
79
  absl::StatusOr<std::vector<std::string>> getStringArray(const std::string& name,
80
                                                          bool allow_empty) const override;
81
  absl::StatusOr<std::vector<ObjectSharedPtr>> asObjectArray() const override;
82
78
  absl::StatusOr<std::string> asString() const override { return stringValue(); }
83
  std::string asJsonString() const override;
84

            
85
  bool empty() const override;
86
  bool hasObject(const std::string& name) const override;
87
  absl::Status iterate(const ObjectCallback& callback) const override;
88
  void validateSchema(const std::string&) const override;
89

            
90
private:
91
  enum class Type {
92
    Array,
93
    Boolean,
94
    Double,
95
    Integer,
96
    Null,
97
    Object,
98
    String,
99
  };
100
60
  static const char* typeAsString(Type t) {
101
60
    switch (t) {
102
1
    case Type::Array:
103
1
      return "Array";
104
1
    case Type::Boolean:
105
1
      return "Boolean";
106
1
    case Type::Double:
107
1
      return "Double";
108
2
    case Type::Integer:
109
2
      return "Integer";
110
1
    case Type::Null:
111
1
      return "Null";
112
27
    case Type::Object:
113
27
      return "Object";
114
27
    case Type::String:
115
27
      return "String";
116
60
    }
117

            
118
    return "";
119
60
  }
120

            
121
  struct Value {
122
    std::vector<FieldSharedPtr> array_value_;
123
    bool boolean_value_;
124
    double double_value_;
125
    int64_t integer_value_;
126
    std::map<std::string, FieldSharedPtr> object_value_;
127
    std::string string_value_;
128
  };
129

            
130
18263
  explicit Field(Type type) : type_(type) {}
131
22019
  explicit Field(const std::string& value) : type_(Type::String) { value_.string_value_ = value; }
132
3472
  explicit Field(int64_t value) : type_(Type::Integer) { value_.integer_value_ = value; }
133
76
  explicit Field(double value) : type_(Type::Double) { value_.double_value_ = value; }
134
625
  explicit Field(bool value) : type_(Type::Boolean) { value_.boolean_value_ = value; }
135

            
136
55023
  bool isType(Type type) const { return type == type_; }
137
51935
  absl::Status checkType(Type type) const {
138
51935
    if (!isType(type)) {
139
30
      return absl::InvalidArgumentError(fmt::format(
140
30
          "JSON field from line {} accessed with type '{}' does not match actual type '{}'.",
141
30
          line_number_start_, typeAsString(type), typeAsString(type_)));
142
30
    }
143
51905
    return absl::OkStatus();
144
51935
  }
145

            
146
  // Value return type functions.
147
1687
  absl::StatusOr<std::string> stringValue() const {
148
1687
    RETURN_IF_NOT_OK(checkType(Type::String));
149
1661
    return value_.string_value_;
150
1687
  }
151
151
  absl::StatusOr<std::vector<FieldSharedPtr>> arrayValue() const {
152
151
    RETURN_IF_NOT_OK(checkType(Type::Array));
153
151
    return value_.array_value_;
154
151
  }
155
167
  absl::StatusOr<bool> booleanValue() const {
156
167
    RETURN_IF_NOT_OK(checkType(Type::Boolean));
157
167
    return value_.boolean_value_;
158
167
  }
159
29
  absl::StatusOr<double> doubleValue() const {
160
29
    RETURN_IF_NOT_OK(checkType(Type::Double));
161
29
    return value_.double_value_;
162
29
  }
163
331
  absl::StatusOr<int64_t> integerValue() const {
164
331
    RETURN_IF_NOT_OK(checkType(Type::Integer));
165
331
    return value_.integer_value_;
166
331
  }
167

            
168
  nlohmann::json asJsonDocument() const;
169
  static void buildJsonDocument(const Field& field, nlohmann::json& value);
170

            
171
  uint64_t line_number_start_ = 0;
172
  uint64_t line_number_end_ = 0;
173
  const Type type_;
174
  Value value_;
175
};
176

            
177
/**
178
 * Consume events from SAX callbacks to build JSON Field.
179
 */
180
class ObjectHandler : public nlohmann::json_sax<nlohmann::json> {
181
public:
182
964
  ObjectHandler() = default;
183

            
184
  bool start_object(std::size_t) override;
185
  bool end_object() override;
186
  bool key(std::string& val) override;
187
  bool start_array(std::size_t) override;
188
  bool end_array() override;
189
624
  bool boolean(bool value) override { return handleValueEvent(Field::createValue(value)); }
190
7
  bool number_integer(int64_t value) override {
191
7
    return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
192
7
  }
193
3466
  bool number_unsigned(uint64_t value) override {
194
3466
    if (value > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
195
      // Envoy's code is discouraging the use of exceptions. The following sets
196
      // the error details as if an exception occurs, and returns false to stop
197
      // parsing.
198
1
      error_ = fmt::format("JSON value from line {} is larger than int64_t (not supported)",
199
1
                           line_number_);
200
1
      error_position_ = absl::StrCat("line: ", line_number_);
201
1
      return false;
202
1
    }
203
3465
    return handleValueEvent(Field::createValue(static_cast<int64_t>(value)));
204
3466
  }
205
54
  bool number_float(double value, const std::string&) override {
206
54
    return handleValueEvent(Field::createValue(value));
207
54
  }
208
1085
  bool null() override { return handleValueEvent(Field::createNull()); }
209
21884
  bool string(std::string& value) override { return handleValueEvent(Field::createValue(value)); }
210
  bool binary(binary_t&) override { return false; }
211
  bool parse_error(std::size_t at, const std::string& token,
212
80
                   const nlohmann::detail::exception& ex) override {
213
    // Parse errors are formatted like "[json.exception.parse_error.101] parse error: explanatory
214
    // string." or "[json.exception.parse_error.101] parser error at (position): explanatory
215
    // string.". All errors start with "[json.exception.<error_type>.<error_num]" see:
216
    // https://json.nlohmann.me/home/exceptions/#parse-errors
217
    // The `parse_error` method will be called also for non-parse errors.
218
80
    absl::string_view error = ex.what();
219

            
220
    // Colon will always exist in the parse error. For non-parse error use the
221
    // ending ']' as a separator.
222
80
    auto end = error.find(": ");
223
80
    auto prefix_end = error.find(']');
224
80
    if (end != std::string::npos) {
225
      // Extract portion after ": " to get error string.
226
79
      error_ = std::string(error.substr(end + 2));
227
      // Extract position information if present.
228
79
      auto start = error.find("at ");
229
79
      if (start != std::string::npos && (start + 3) < end) {
230
79
        start += 3;
231
79
        error_position_ = absl::StrCat(error.substr(start, end - start), ", token ", token);
232
79
      }
233
79
    } else if ((prefix_end != std::string::npos) && (absl::StartsWith(error, ErrorPrefix))) {
234
      // Non-parse error, fetching position from the arguments as it is not
235
      // present in the error string.
236
1
      error_position_ = absl::StrCat("position: ", at);
237
1
      error_ = std::string(error.substr(prefix_end + 1));
238
1
    } else {
239
      IS_ENVOY_BUG("Error string not present. Check nlohmann/json "
240
                   "documentation in case error string changed.");
241
    }
242
80
    return false;
243
80
  }
244

            
245
964
  bool hasParseError() { return !error_.empty(); }
246
81
  std::string getParseError() { return error_; }
247
81
  std::string getErrorPosition() { return error_position_; }
248

            
249
883
  ObjectSharedPtr getRoot() { return root_; }
250

            
251
  int line_number_{1};
252

            
253
private:
254
  bool handleValueEvent(FieldSharedPtr ptr);
255

            
256
  enum class State {
257
    ExpectRoot,
258
    ExpectKeyOrEndObject,
259
    ExpectValueOrStartObjectArray,
260
    ExpectArrayValueOrEndArray,
261
    ExpectFinished,
262
  };
263
  State state_{State::ExpectRoot};
264

            
265
  std::stack<FieldSharedPtr> stack_;
266
  std::string key_;
267

            
268
  FieldSharedPtr root_;
269

            
270
  std::string error_;
271
  std::string error_position_;
272

            
273
  static constexpr absl::string_view ErrorPrefix = "[json.exception.";
274
};
275

            
276
struct JsonContainer {
277
2892
  JsonContainer(const char* ch, ObjectHandler* handler) : data(ch), handler_(handler) {}
278
  const char* data;
279
  ObjectHandler* handler_;
280
};
281

            
282
struct JsonIterator {
283
  using difference_type = std::ptrdiff_t;            // NOLINT(readability-identifier-naming)
284
  using value_type = char;                           // NOLINT(readability-identifier-naming)
285
  using pointer = const char*;                       // NOLINT(readability-identifier-naming)
286
  using reference = const char&;                     // NOLINT(readability-identifier-naming)
287
  using iterator_category = std::input_iterator_tag; // NOLINT(readability-identifier-naming)
288

            
289
1521675
  JsonIterator& operator++() {
290
1521675
    ++ptr.data;
291
1521675
    return *this;
292
1521675
  }
293

            
294
1522571
  bool operator!=(const JsonIterator& rhs) const { return rhs.ptr.data != ptr.data; }
295

            
296
1521675
  reference operator*() {
297
1521675
    const char& ch = *(ptr.data);
298
1521675
    if (ch == '\n') {
299
46567
      ptr.handler_->line_number_++;
300
46567
    }
301
1521675
    return ch;
302
1521675
  }
303

            
304
  JsonContainer ptr;
305
};
306

            
307
964
JsonIterator begin(const JsonContainer& c) {
308
964
  return JsonIterator{JsonContainer(c.data, c.handler_)};
309
964
}
310

            
311
964
JsonIterator end(const JsonContainer& c) {
312
964
  return JsonIterator{JsonContainer(c.data + strlen(c.data), c.handler_)};
313
964
}
314

            
315
98
void Field::buildJsonDocument(const Field& field, nlohmann::json& value) {
316
98
  switch (field.type_) {
317
19
  case Type::Array: {
318
41
    for (const auto& element : field.value_.array_value_) {
319
41
      switch (element->type_) {
320
4
      case Type::Array:
321
12
      case Type::Object: {
322
12
        nlohmann::json nested_value;
323
12
        buildJsonDocument(*element, nested_value);
324
12
        value.push_back(nested_value);
325
12
        break;
326
4
      }
327
1
      case Type::Boolean:
328
1
        value.push_back(element->value_.boolean_value_);
329
1
        break;
330
4
      case Type::Double:
331
4
        value.push_back(element->value_.double_value_);
332
4
        break;
333
4
      case Type::Integer:
334
4
        value.push_back(element->value_.integer_value_);
335
4
        break;
336
1
      case Type::Null:
337
1
        value.push_back(nlohmann::json::value_t::null);
338
1
        break;
339
19
      case Type::String:
340
19
        value.push_back(element->value_.string_value_);
341
41
      }
342
41
    }
343
19
    break;
344
19
  }
345
79
  case Type::Object: {
346
270
    for (const auto& item : field.value_.object_value_) {
347
270
      auto name = std::string(item.first);
348

            
349
270
      switch (item.second->type_) {
350
8
      case Type::Array:
351
35
      case Type::Object: {
352
35
        nlohmann::json nested_value;
353
35
        buildJsonDocument(*item.second, nested_value);
354
35
        value.emplace(name, nested_value);
355
35
        break;
356
8
      }
357
7
      case Type::Boolean:
358
7
        value.emplace(name, item.second->value_.boolean_value_);
359
7
        break;
360
31
      case Type::Double:
361
31
        value.emplace(name, item.second->value_.double_value_);
362
31
        break;
363
54
      case Type::Integer:
364
54
        value.emplace(name, item.second->value_.integer_value_);
365
54
        break;
366
3
      case Type::Null:
367
3
        value.emplace(name, nlohmann::json::value_t::null);
368
3
        break;
369
140
      case Type::String:
370
140
        value.emplace(name, item.second->value_.string_value_);
371
140
        break;
372
270
      }
373
270
    }
374
79
    break;
375
79
  }
376
79
  case Type::Null: {
377
    break;
378
79
  }
379
  case Type::Boolean:
380
    FALLTHRU;
381
  case Type::Double:
382
    FALLTHRU;
383
  case Type::Integer:
384
    FALLTHRU;
385
  case Type::String:
386
    PANIC("not implemented");
387
98
  }
388
98
}
389

            
390
51
nlohmann::json Field::asJsonDocument() const {
391
51
  nlohmann::json j;
392
51
  buildJsonDocument(*this, j);
393
51
  return j;
394
51
}
395

            
396
10
uint64_t Field::hash() const { return HashUtil::xxHash64(asJsonString()); }
397

            
398
241
absl::StatusOr<ValueType> Field::getValue(const std::string& name) const {
399
241
  auto value_itr = value_.object_value_.find(name);
400
241
  if (value_itr == value_.object_value_.end()) {
401
17
    return absl::NotFoundError(fmt::format("key '{}' missing from lines {}-{}", name,
402
17
                                           line_number_start_, line_number_end_));
403
17
  }
404
224
  switch (value_itr->second->type_) {
405
4
  case Type::Boolean:
406
4
    return value_itr->second->booleanValue();
407
14
  case Type::Double:
408
14
    return value_itr->second->doubleValue();
409
17
  case Type::Integer:
410
17
    return value_itr->second->integerValue();
411
188
  case Type::String:
412
188
    return value_itr->second->stringValue();
413
1
  default:
414
1
    return absl::InternalError(fmt::format("key '{}' not a value type from lines {}-{}", name,
415
1
                                           line_number_start_, line_number_end_));
416
224
  }
417
224
}
418

            
419
309
absl::StatusOr<bool> Field::getBoolean(const std::string& name) const {
420
309
  RETURN_IF_NOT_OK(checkType(Type::Object));
421
309
  auto value_itr = value_.object_value_.find(name);
422
309
  if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Boolean)) {
423
146
    return absl::InvalidArgumentError(
424
146
        fmt::format("key '{}' missing or not a boolean from lines {}-{}", name, line_number_start_,
425
146
                    line_number_end_));
426
146
  }
427
163
  return value_itr->second->booleanValue();
428
309
}
429

            
430
4
absl::StatusOr<bool> Field::getBoolean(const std::string& name, bool default_value) const {
431
4
  RETURN_IF_NOT_OK(checkType(Type::Object));
432
4
  auto value_itr = value_.object_value_.find(name);
433
4
  if (value_itr != value_.object_value_.end()) {
434
3
    return getBoolean(name);
435
3
  }
436
1
  return default_value;
437
4
}
438

            
439
26
absl::StatusOr<double> Field::getDouble(const std::string& name) const {
440
26
  RETURN_IF_NOT_OK(checkType(Type::Object));
441
24
  auto value_itr = value_.object_value_.find(name);
442
24
  if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Double)) {
443
9
    return absl::InvalidArgumentError(
444
9
        fmt::format("key '{}' missing or not a double from lines {}-{}", name, line_number_start_,
445
9
                    line_number_end_));
446
9
  }
447
15
  return value_itr->second->doubleValue();
448
24
}
449

            
450
2
absl::StatusOr<double> Field::getDouble(const std::string& name, double default_value) const {
451
2
  RETURN_IF_NOT_OK(checkType(Type::Object));
452
2
  auto value_itr = value_.object_value_.find(name);
453
2
  if (value_itr != value_.object_value_.end()) {
454
1
    return getDouble(name);
455
1
  }
456
1
  return default_value;
457
2
}
458

            
459
333
absl::StatusOr<int64_t> Field::getInteger(const std::string& name) const {
460
333
  RETURN_IF_NOT_OK(checkType(Type::Object));
461
333
  auto value_itr = value_.object_value_.find(name);
462
333
  if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Integer)) {
463
19
    return absl::InvalidArgumentError(
464
19
        fmt::format("key '{}' missing or not an integer from lines {}-{}", name, line_number_start_,
465
19
                    line_number_end_));
466
19
  }
467
314
  return value_itr->second->integerValue();
468
333
}
469

            
470
10
absl::StatusOr<int64_t> Field::getInteger(const std::string& name, int64_t default_value) const {
471
10
  RETURN_IF_NOT_OK(checkType(Type::Object));
472
10
  auto value_itr = value_.object_value_.find(name);
473
10
  if (value_itr != value_.object_value_.end()) {
474
8
    return getInteger(name);
475
8
  }
476
2
  return default_value;
477
10
}
478

            
479
1067
absl::StatusOr<ObjectSharedPtr> Field::getObject(const std::string& name, bool allow_empty) const {
480
1067
  RETURN_IF_NOT_OK(checkType(Type::Object));
481
1067
  auto value_itr = value_.object_value_.find(name);
482
1067
  if (value_itr == value_.object_value_.end()) {
483
172
    if (allow_empty) {
484
1
      return createObject();
485
171
    } else {
486
171
      return absl::NotFoundError(fmt::format("key '{}' missing from lines {}-{}", name,
487
171
                                             line_number_start_, line_number_end_));
488
171
    }
489
959
  } else if (!value_itr->second->isType(Type::Object)) {
490
10
    return absl::InternalError(fmt::format("key '{}' not an object from line {}", name,
491
10
                                           value_itr->second->line_number_start_));
492
10
  }
493

            
494
885
  return value_itr->second;
495
1067
}
496

            
497
absl::StatusOr<std::vector<ObjectSharedPtr>> Field::getObjectArray(const std::string& name,
498
163
                                                                   bool allow_empty) const {
499
163
  RETURN_IF_NOT_OK(checkType(Type::Object));
500
163
  auto value_itr = value_.object_value_.find(name);
501
163
  if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Array)) {
502
25
    if (allow_empty && value_itr == value_.object_value_.end()) {
503
1
      std::vector<ObjectSharedPtr> ret;
504
1
      return ret;
505
1
    }
506
24
    return absl::InvalidArgumentError(
507
24
        fmt::format("key '{}' missing or not an array from lines {}-{}", name, line_number_start_,
508
24
                    line_number_end_));
509
25
  }
510

            
511
138
  auto array_value_or_error = value_itr->second->arrayValue();
512
138
  RETURN_IF_NOT_OK_REF(array_value_or_error.status());
513
138
  std::vector<FieldSharedPtr>& array_value = array_value_or_error.value();
514
138
  std::vector<ObjectSharedPtr> ret{array_value.begin(), array_value.end()};
515
138
  return ret;
516
138
}
517

            
518
1652
absl::StatusOr<std::string> Field::getString(const std::string& name) const {
519
1652
  RETURN_IF_NOT_OK(checkType(Type::Object));
520
1651
  auto value_itr = value_.object_value_.find(name);
521
1651
  if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::String)) {
522
258
    return absl::InvalidArgumentError(
523
258
        fmt::format("key '{}' missing or not a string from lines {}-{}", name, line_number_start_,
524
258
                    line_number_end_));
525
258
  }
526
1393
  return value_itr->second->stringValue();
527
1651
}
528

            
529
absl::StatusOr<std::string> Field::getString(const std::string& name,
530
49
                                             const std::string& default_value) const {
531
49
  RETURN_IF_NOT_OK(checkType(Type::Object));
532
49
  auto value_itr = value_.object_value_.find(name);
533
49
  if (value_itr != value_.object_value_.end()) {
534
29
    return getString(name);
535
29
  }
536
20
  return default_value;
537
49
}
538

            
539
absl::StatusOr<std::vector<std::string>> Field::getStringArray(const std::string& name,
540
17
                                                               bool allow_empty) const {
541
17
  RETURN_IF_NOT_OK(checkType(Type::Object));
542
17
  std::vector<std::string> string_array;
543
17
  auto value_itr = value_.object_value_.find(name);
544
17
  if (value_itr == value_.object_value_.end() || !value_itr->second->isType(Type::Array)) {
545
4
    if (allow_empty && value_itr == value_.object_value_.end()) {
546
1
      return string_array;
547
1
    }
548
3
    return absl::InvalidArgumentError(
549
3
        fmt::format("key '{}' missing or not an array from lines {}-{}", name, line_number_start_,
550
3
                    line_number_end_));
551
4
  }
552

            
553
13
  auto array_value_or_error = value_itr->second->arrayValue();
554
13
  RETURN_IF_NOT_OK_REF(array_value_or_error.status());
555
13
  std::vector<FieldSharedPtr>& array = array_value_or_error.value();
556
13
  string_array.reserve(array.size());
557
15
  for (const auto& element : array) {
558
15
    if (!element->isType(Type::String)) {
559
1
      return absl::InvalidArgumentError(fmt::format(
560
1
          "JSON array '{}' from line {} does not contain all strings", name, line_number_start_));
561
1
    }
562
14
    RETURN_IF_NOT_OK_REF(element->stringValue().status());
563
14
    string_array.push_back(element->stringValue().value());
564
14
  }
565

            
566
12
  return string_array;
567
13
}
568

            
569
292
absl::StatusOr<std::vector<ObjectSharedPtr>> Field::asObjectArray() const {
570
292
  RETURN_IF_NOT_OK(checkType(Type::Array));
571
291
  return std::vector<ObjectSharedPtr>{value_.array_value_.begin(), value_.array_value_.end()};
572
292
}
573

            
574
51
std::string Field::asJsonString() const {
575
51
  nlohmann::json j = asJsonDocument();
576
  // Call with defaults except in the case of UTF-8 errors which we replace
577
  // invalid UTF-8 characters instead of throwing an exception.
578
51
  return j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
579
51
}
580

            
581
17
bool Field::empty() const {
582
17
  if (isType(Type::Object)) {
583
15
    return value_.object_value_.empty();
584
15
  } else if (isType(Type::Array)) {
585
2
    return value_.array_value_.empty();
586
2
  }
587
  IS_ENVOY_BUG("Json does not support empty() on types other than array and object");
588
  return false;
589
17
}
590

            
591
1590
bool Field::hasObject(const std::string& name) const {
592
1590
  if (!checkType(Type::Object).ok()) {
593
    IS_ENVOY_BUG("HasObject called on non-object");
594
    return false;
595
  }
596
1590
  auto value_itr = value_.object_value_.find(name);
597
1590
  return value_itr != value_.object_value_.end();
598
1590
}
599

            
600
578
absl::Status Field::iterate(const ObjectCallback& callback) const {
601
578
  RETURN_IF_NOT_OK(checkType(Type::Object));
602
1392
  for (const auto& item : value_.object_value_) {
603
1392
    bool stop_iteration = !callback(item.first, *item.second);
604
1392
    if (stop_iteration) {
605
6
      break;
606
6
    }
607
1392
  }
608
578
  return absl::OkStatus();
609
578
}
610

            
611
1
void Field::validateSchema(const std::string&) const {
612
1
  IS_ENVOY_BUG("validateSchema not implemented");
613
1
}
614

            
615
12626
bool ObjectHandler::start_object(std::size_t) {
616
12626
  FieldSharedPtr object = Field::createObject();
617
12626
  object->setLineNumberStart(line_number_);
618

            
619
12626
  switch (state_) {
620
3874
  case State::ExpectValueOrStartObjectArray:
621
3874
    THROW_IF_NOT_OK(stack_.top()->insert(key_, object));
622
3874
    stack_.push(object);
623
3874
    state_ = State::ExpectKeyOrEndObject;
624
3874
    return true;
625
7879
  case State::ExpectArrayValueOrEndArray:
626
7879
    THROW_IF_NOT_OK(stack_.top()->append(object));
627
7879
    stack_.push(object);
628
7879
    state_ = State::ExpectKeyOrEndObject;
629
7879
    return true;
630
873
  case State::ExpectRoot:
631
873
    root_ = object;
632
873
    stack_.push(object);
633
873
    state_ = State::ExpectKeyOrEndObject;
634
873
    return true;
635
  case State::ExpectKeyOrEndObject:
636
    FALLTHRU;
637
  case State::ExpectFinished:
638
    PANIC("not implemented");
639
12626
  }
640
  return false;
641
12626
}
642

            
643
12610
bool ObjectHandler::end_object() {
644
12610
  if (state_ == State::ExpectKeyOrEndObject) {
645
12610
    stack_.top()->setLineNumberEnd(line_number_);
646
12610
    stack_.pop();
647

            
648
12610
    if (stack_.empty()) {
649
857
      state_ = State::ExpectFinished;
650
11869
    } else if (stack_.top()->isObject()) {
651
3874
      state_ = State::ExpectKeyOrEndObject;
652
8825
    } else if (stack_.top()->isArray()) {
653
7879
      state_ = State::ExpectArrayValueOrEndArray;
654
7879
    }
655
12610
    return true;
656
12610
  }
657
  PANIC("parsing error not handled");
658
}
659

            
660
30980
bool ObjectHandler::key(std::string& val) {
661
30980
  if (state_ == State::ExpectKeyOrEndObject) {
662
30980
    key_ = val;
663
30980
    state_ = State::ExpectValueOrStartObjectArray;
664
30980
    return true;
665
30980
  }
666
  PANIC("parsing error not handled");
667
}
668

            
669
4492
bool ObjectHandler::start_array(std::size_t) {
670
4492
  FieldSharedPtr array = Field::createArray();
671
4492
  array->setLineNumberStart(line_number_);
672

            
673
4492
  switch (state_) {
674
4428
  case State::ExpectValueOrStartObjectArray:
675
4428
    THROW_IF_NOT_OK(stack_.top()->insert(key_, array));
676
4428
    stack_.push(array);
677
4428
    state_ = State::ExpectArrayValueOrEndArray;
678
4428
    return true;
679
3
  case State::ExpectArrayValueOrEndArray:
680
3
    THROW_IF_NOT_OK(stack_.top()->append(array));
681
3
    stack_.push(array);
682
3
    return true;
683
61
  case State::ExpectRoot:
684
61
    root_ = array;
685
61
    stack_.push(array);
686
61
    state_ = State::ExpectArrayValueOrEndArray;
687
61
    return true;
688
  default:
689
    PANIC("parsing error not handled");
690
4492
  }
691
4492
}
692

            
693
4455
bool ObjectHandler::end_array() {
694
4455
  switch (state_) {
695
4455
  case State::ExpectArrayValueOrEndArray:
696
4455
    stack_.top()->setLineNumberEnd(line_number_);
697
4455
    stack_.pop();
698

            
699
4455
    if (stack_.empty()) {
700
24
      state_ = State::ExpectFinished;
701
4448
    } else if (stack_.top()->isObject()) {
702
4428
      state_ = State::ExpectKeyOrEndObject;
703
4428
    } else if (stack_.top()->isArray()) {
704
3
      state_ = State::ExpectArrayValueOrEndArray;
705
3
    }
706

            
707
4455
    return true;
708
  default:
709
    PANIC("parsing error not handled");
710
4455
  }
711
4455
}
712

            
713
27119
bool ObjectHandler::handleValueEvent(FieldSharedPtr ptr) {
714
27119
  ptr->setLineNumberStart(line_number_);
715

            
716
27119
  switch (state_) {
717
22677
  case State::ExpectValueOrStartObjectArray:
718
22677
    state_ = State::ExpectKeyOrEndObject;
719
22677
    THROW_IF_NOT_OK(stack_.top()->insert(key_, ptr));
720
22677
    return true;
721
4437
  case State::ExpectArrayValueOrEndArray:
722
4437
    THROW_IF_NOT_OK(stack_.top()->append(ptr));
723
4437
    return true;
724
5
  default:
725
5
    return true;
726
27119
  }
727
27119
}
728

            
729
} // namespace
730

            
731
964
absl::StatusOr<ObjectSharedPtr> Factory::loadFromString(const std::string& json) {
732
964
  ObjectHandler handler;
733
964
  auto json_container = JsonContainer(json.c_str(), &handler);
734

            
735
964
  nlohmann::json::sax_parse(json_container, &handler);
736

            
737
964
  if (handler.hasParseError()) {
738
81
    return absl::InternalError(fmt::format("JSON supplied is not valid. Error({}): {}\n",
739
81
                                           handler.getErrorPosition(), handler.getParseError()));
740
81
  }
741
883
  return handler.getRoot();
742
964
}
743

            
744
absl::StatusOr<FieldSharedPtr>
745
loadFromProtobufStructInternal(const Protobuf::Struct& protobuf_struct);
746

            
747
absl::StatusOr<FieldSharedPtr>
748
181
loadFromProtobufValueInternal(const Protobuf::Value& protobuf_value) {
749
181
  switch (protobuf_value.kind_case()) {
750
135
  case Protobuf::Value::kStringValue:
751
135
    return Field::createValue(protobuf_value.string_value());
752
22
  case Protobuf::Value::kNumberValue:
753
22
    return Field::createValue(protobuf_value.number_value());
754
1
  case Protobuf::Value::kBoolValue:
755
1
    return Field::createValue(protobuf_value.bool_value());
756
1
  case Protobuf::Value::kNullValue:
757
1
    return Field::createNull();
758
7
  case Protobuf::Value::kListValue: {
759
7
    FieldSharedPtr array = Field::createArray();
760
20
    for (const auto& list_value : protobuf_value.list_value().values()) {
761
20
      absl::StatusOr<FieldSharedPtr> proto_or_error = loadFromProtobufValueInternal(list_value);
762
20
      RETURN_IF_NOT_OK_REF(proto_or_error.status());
763
20
      RETURN_IF_NOT_OK(array->append(*proto_or_error));
764
20
    }
765
7
    return array;
766
7
  }
767
14
  case Protobuf::Value::kStructValue:
768
14
    return loadFromProtobufStructInternal(protobuf_value.struct_value());
769
1
  case Protobuf::Value::KIND_NOT_SET:
770
1
    break;
771
181
  }
772
1
  return absl::InvalidArgumentError("Protobuf value case not implemented");
773
181
}
774

            
775
absl::StatusOr<FieldSharedPtr>
776
51
loadFromProtobufStructInternal(const Protobuf::Struct& protobuf_struct) {
777
51
  auto root = Field::createObject();
778
161
  for (const auto& field : protobuf_struct.fields()) {
779
161
    absl::StatusOr<FieldSharedPtr> proto_or_error = loadFromProtobufValueInternal(field.second);
780
161
    RETURN_IF_NOT_OK_REF(proto_or_error.status());
781
160
    RETURN_IF_NOT_OK(root->insert(field.first, *proto_or_error));
782
160
  }
783

            
784
50
  return root;
785
51
}
786

            
787
37
ObjectSharedPtr Factory::loadFromProtobufStruct(const Protobuf::Struct& protobuf_struct) {
788
37
  return THROW_OR_RETURN_VALUE(loadFromProtobufStructInternal(protobuf_struct), ObjectSharedPtr);
789
37
}
790

            
791
1112013
std::string Factory::serialize(absl::string_view str) {
792
1112013
  nlohmann::json j(str);
793
1112013
  return j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
794
1112013
}
795

            
796
4
template <typename T> std::string Factory::serialize(const T& items) {
797
4
  nlohmann::json j = nlohmann::json(items);
798
4
  return j.dump();
799
4
}
800

            
801
18
std::vector<uint8_t> Factory::jsonToMsgpack(const std::string& json_string) {
802
18
  return nlohmann::json::to_msgpack(nlohmann::json::parse(json_string, nullptr, false));
803
18
}
804

            
805
// Template instantiation for serialize function.
806
template std::string Factory::serialize(const std::list<std::string>& items);
807
template std::string Factory::serialize(const absl::flat_hash_set<std::string>& items);
808
template std::string Factory::serialize(
809
    const absl::flat_hash_map<std::string, absl::flat_hash_map<std::string, int>>& items);
810

            
811
} // namespace Nlohmann
812
} // namespace Json
813
} // namespace Envoy