-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathjson_helpers.cpp
More file actions
157 lines (145 loc) · 4.94 KB
/
json_helpers.cpp
File metadata and controls
157 lines (145 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "databento/detail/json_helpers.hpp"
#include <numeric> // accumulate
#include <optional>
#include <sstream> // istringstream
#include <string>
namespace databento::detail {
void SetIfNotEmpty(httplib::Params* params, const std::string& key,
const std::string& value) {
if (!value.empty()) {
params->emplace(key, value);
}
}
void SetIfNotEmpty(httplib::Params* params, const std::string& key,
const std::vector<databento::JobState>& states) {
if (!states.empty()) {
std::string value = std::accumulate(
states.begin(), states.end(), std::string{},
[](std::string acc, databento::JobState state) {
return acc.empty() ? databento::ToString(state)
: std::move(acc) + "," + databento::ToString(state);
});
params->emplace(key, std::move(value));
}
}
const nlohmann::json& CheckedAt(std::string_view endpoint, const nlohmann::json& json,
std::string_view key) {
if (json.contains(key)) {
return json.at(key);
}
throw JsonResponseError::MissingKey(endpoint, key);
}
template <>
bool ParseAt(std::string_view endpoint, const nlohmann::json& json,
std::string_view key) {
const auto& val_json = CheckedAt(endpoint, json, key);
if (!val_json.is_boolean()) {
throw JsonResponseError::TypeMismatch(endpoint, std::string{key} + " bool",
val_json);
}
return val_json;
}
template <>
std::string ParseAt(std::string_view endpoint, const nlohmann::json& json,
std::string_view key) {
const auto s = ParseAt<std::optional<std::string>>(endpoint, json, key);
if (s) {
return *s;
}
return {};
}
template <>
std::optional<std::string> ParseAt(std::string_view endpoint,
const nlohmann::json& json, std::string_view key) {
const auto& val_json = CheckedAt(endpoint, json, key);
if (val_json.is_null()) {
return {};
}
if (!val_json.is_string()) {
throw JsonResponseError::TypeMismatch(endpoint, std::string{key} + " string",
val_json);
}
return std::optional<std::string>{val_json};
}
template <>
std::uint64_t ParseAt(std::string_view endpoint, const nlohmann::json& json,
std::string_view key) {
const auto& val_json = CheckedAt(endpoint, json, key);
if (val_json.is_null()) {
return 0;
}
if (!val_json.is_number_unsigned()) {
throw JsonResponseError::TypeMismatch(
endpoint, std::string{key} + " unsigned number", val_json);
}
return val_json;
}
template <>
std::uint16_t ParseAt(std::string_view endpoint, const nlohmann::json& json,
std::string_view key) {
const auto& val_json = CheckedAt(endpoint, json, key);
if (val_json.is_null()) {
return 0;
}
if (!val_json.is_number_unsigned()) {
throw JsonResponseError::TypeMismatch(
endpoint, std::string{key} + " unsigned number", val_json);
}
return val_json;
}
template <>
double ParseAt(std::string_view endpoint, const nlohmann::json& json,
std::string_view key) {
const auto& val_json = CheckedAt(endpoint, json, key);
if (val_json.is_null()) {
return 0;
}
if (!val_json.is_number()) {
throw JsonResponseError::TypeMismatch(endpoint, std::string{key} + " number",
val_json);
}
return val_json;
}
template <>
std::vector<std::string> ParseAt(std::string_view endpoint, const nlohmann::json& json,
std::string_view key) {
const auto& symbols_json = CheckedAt(endpoint, json, key);
// if there's only one symbol, it returns a string not an array
if (symbols_json.is_string()) {
return {symbols_json};
}
if (!symbols_json.is_array()) {
throw JsonResponseError::TypeMismatch(endpoint, std::string{key} + " array", json);
}
return {symbols_json.begin(), symbols_json.end()};
}
template <>
date::year_month_day ParseAt(std::string_view endpoint, const nlohmann::json& json,
std::string_view key) {
std::string raw_start = detail::CheckedAt(endpoint, json, key);
std::istringstream start_stream{raw_start};
date::year_month_day start;
start_stream >> date::parse("%F", start);
if (start_stream.fail()) {
throw JsonResponseError::TypeMismatch(endpoint, "YYYY-MM-DD date string",
raw_start);
}
return start;
}
template <>
std::optional<std::uint8_t> ParseAt(std::string_view endpoint,
const nlohmann::json& json, std::string_view key) {
if (!json.contains(key)) {
return {};
}
const auto& val_json = json.at(key);
if (val_json.is_null()) {
return {};
}
if (!val_json.is_number_unsigned()) {
throw JsonResponseError::TypeMismatch(
endpoint, std::string{key} + " unsigned number", val_json);
}
return val_json.get<std::uint8_t>();
}
} // namespace databento::detail