1
#include "source/common/json/json_utility.h"
2

            
3
namespace Envoy {
4
namespace Json {
5

            
6
namespace {
7

            
8
void structValueToJson(const Protobuf::Struct& struct_value, StringStreamer::Map& level);
9
void listValueToJson(const Protobuf::ListValue& list_value, StringStreamer::Array& level);
10

            
11
529
void valueToJson(const Protobuf::Value& value, StringStreamer::Level& level) {
12
529
  switch (value.kind_case()) {
13
  case Protobuf::Value::KIND_NOT_SET:
14
  case Protobuf::Value::kNullValue:
15
    level.addNull();
16
    break;
17
343
  case Protobuf::Value::kNumberValue:
18
343
    level.addNumber(value.number_value());
19
343
    break;
20
99
  case Protobuf::Value::kStringValue:
21
99
    level.addString(value.string_value());
22
99
    break;
23
43
  case Protobuf::Value::kBoolValue:
24
43
    level.addBool(value.bool_value());
25
43
    break;
26
34
  case Protobuf::Value::kStructValue:
27
34
    structValueToJson(value.struct_value(), *level.addMap());
28
34
    break;
29
10
  case Protobuf::Value::kListValue:
30
10
    listValueToJson(value.list_value(), *level.addArray());
31
10
    break;
32
529
  }
33
529
}
34

            
35
101
void structValueToJson(const Protobuf::Struct& struct_value, StringStreamer::Map& map) {
36
101
  using PairRefWrapper =
37
101
      std::reference_wrapper<const Protobuf::Map<std::string, Protobuf::Value>::value_type>;
38
101
  absl::InlinedVector<PairRefWrapper, 8> sorted_fields;
39
101
  sorted_fields.reserve(struct_value.fields_size());
40

            
41
512
  for (const auto& field : struct_value.fields()) {
42
512
    sorted_fields.emplace_back(field);
43
512
  }
44
  // Sort the keys to make the output deterministic.
45
101
  std::sort(sorted_fields.begin(), sorted_fields.end(),
46
1817
            [](PairRefWrapper a, PairRefWrapper b) { return a.get().first < b.get().first; });
47

            
48
512
  for (const PairRefWrapper field : sorted_fields) {
49
512
    map.addKey(field.get().first);
50
512
    valueToJson(field.get().second, map);
51
512
  }
52
101
}
53

            
54
12
void listValueToJson(const Protobuf::ListValue& list_value, StringStreamer::Array& arr) {
55
17
  for (const Protobuf::Value& value : list_value.values()) {
56
17
    valueToJson(value, arr);
57
17
  }
58
12
}
59

            
60
} // namespace
61

            
62
916
void Utility::appendValueToString(const Protobuf::Value& value, std::string& dest) {
63
916
  StringStreamer streamer(dest);
64
916
  switch (value.kind_case()) {
65
1
  case Protobuf::Value::KIND_NOT_SET:
66
261
  case Protobuf::Value::kNullValue:
67
261
    streamer.addNull();
68
261
    break;
69
69
  case Protobuf::Value::kNumberValue:
70
69
    streamer.addNumber(value.number_value());
71
69
    break;
72
520
  case Protobuf::Value::kStringValue:
73
520
    streamer.addString(value.string_value());
74
520
    break;
75
3
  case Protobuf::Value::kBoolValue:
76
3
    streamer.addBool(value.bool_value());
77
3
    break;
78
61
  case Protobuf::Value::kStructValue:
79
61
    structValueToJson(value.struct_value(), *streamer.makeRootMap());
80
61
    break;
81
2
  case Protobuf::Value::kListValue:
82
2
    listValueToJson(value.list_value(), *streamer.makeRootArray());
83
2
    break;
84
916
  }
85
916
}
86

            
87
6
void Utility::appendStructToString(const Protobuf::Struct& struct_value, std::string& dest) {
88
6
  StringStreamer streamer(dest);
89
6
  structValueToJson(struct_value, *streamer.makeRootMap());
90
6
}
91

            
92
} // namespace Json
93
} // namespace Envoy