|
41 | 41 | #include "iceberg/transform.h" |
42 | 42 | #include "iceberg/type.h" |
43 | 43 | #include "iceberg/util/formatter.h" // IWYU pragma: keep |
| 44 | +#include "iceberg/util/json_util_internal.h" |
44 | 45 | #include "iceberg/util/macros.h" |
45 | 46 | #include "iceberg/util/timepoint.h" |
46 | 47 |
|
@@ -165,185 +166,6 @@ constexpr std::string_view kFileSizeInBytes = "file-size-in-bytes"; |
165 | 166 | constexpr std::string_view kFileFooterSizeInBytes = "file-footer-size-in-bytes"; |
166 | 167 | constexpr std::string_view kBlobMetadata = "blob-metadata"; |
167 | 168 |
|
168 | | -template <typename T> |
169 | | -void SetOptionalField(nlohmann::json& json, std::string_view key, |
170 | | - const std::optional<T>& value) { |
171 | | - if (value.has_value()) { |
172 | | - json[key] = *value; |
173 | | - } |
174 | | -} |
175 | | - |
176 | | -std::string SafeDumpJson(const nlohmann::json& json) { |
177 | | - return json.dump(/*indent=*/-1, /*indent_char=*/' ', /*ensure_ascii=*/false, |
178 | | - nlohmann::detail::error_handler_t::ignore); |
179 | | -} |
180 | | - |
181 | | -template <typename T> |
182 | | -Result<T> GetJsonValueImpl(const nlohmann::json& json, std::string_view key) { |
183 | | - try { |
184 | | - return json.at(key).get<T>(); |
185 | | - } catch (const std::exception& ex) { |
186 | | - return JsonParseError("Failed to parse '{}' from {}: {}", key, SafeDumpJson(json), |
187 | | - ex.what()); |
188 | | - } |
189 | | -} |
190 | | - |
191 | | -template <typename T> |
192 | | -Result<std::optional<T>> GetJsonValueOptional(const nlohmann::json& json, |
193 | | - std::string_view key) { |
194 | | - if (!json.contains(key)) { |
195 | | - return std::nullopt; |
196 | | - } |
197 | | - return GetJsonValueImpl<T>(json, key); |
198 | | -} |
199 | | - |
200 | | -template <typename T> |
201 | | -Result<T> GetJsonValue(const nlohmann::json& json, std::string_view key) { |
202 | | - if (!json.contains(key)) { |
203 | | - return JsonParseError("Missing '{}' in {}", key, SafeDumpJson(json)); |
204 | | - } |
205 | | - return GetJsonValueImpl<T>(json, key); |
206 | | -} |
207 | | - |
208 | | -template <typename T> |
209 | | -Result<T> GetJsonValueOrDefault(const nlohmann::json& json, std::string_view key, |
210 | | - T default_value = T{}) { |
211 | | - if (!json.contains(key)) { |
212 | | - return default_value; |
213 | | - } |
214 | | - return GetJsonValueImpl<T>(json, key); |
215 | | -} |
216 | | - |
217 | | -/// \brief Convert a list of items to a json array. |
218 | | -/// |
219 | | -/// Note that ToJson(const T&) is required for this function to work. |
220 | | -template <typename T> |
221 | | -nlohmann::json::array_t ToJsonList(const std::vector<T>& list) { |
222 | | - return std::accumulate(list.cbegin(), list.cend(), nlohmann::json::array(), |
223 | | - [](nlohmann::json::array_t arr, const T& item) { |
224 | | - arr.push_back(ToJson(item)); |
225 | | - return arr; |
226 | | - }); |
227 | | -} |
228 | | - |
229 | | -/// \brief Overload of the above function for a list of shared pointers. |
230 | | -template <typename T> |
231 | | -nlohmann::json::array_t ToJsonList(const std::vector<std::shared_ptr<T>>& list) { |
232 | | - return std::accumulate(list.cbegin(), list.cend(), nlohmann::json::array(), |
233 | | - [](nlohmann::json::array_t arr, const std::shared_ptr<T>& item) { |
234 | | - arr.push_back(ToJson(*item)); |
235 | | - return arr; |
236 | | - }); |
237 | | -} |
238 | | - |
239 | | -/// \brief Parse a list of items from a JSON object. |
240 | | -/// |
241 | | -/// \param[in] json The JSON object to parse. |
242 | | -/// \param[in] key The key to parse. |
243 | | -/// \param[in] from_json The function to parse an item from a JSON object. |
244 | | -/// \return The list of items. |
245 | | -template <typename T> |
246 | | -Result<std::vector<T>> FromJsonList( |
247 | | - const nlohmann::json& json, std::string_view key, |
248 | | - const std::function<Result<T>(const nlohmann::json&)>& from_json) { |
249 | | - std::vector<T> list{}; |
250 | | - if (json.contains(key)) { |
251 | | - ICEBERG_ASSIGN_OR_RAISE(auto list_json, GetJsonValue<nlohmann::json>(json, key)); |
252 | | - if (!list_json.is_array()) { |
253 | | - return JsonParseError("Cannot parse '{}' from non-array: {}", key, |
254 | | - SafeDumpJson(list_json)); |
255 | | - } |
256 | | - for (const auto& entry_json : list_json) { |
257 | | - ICEBERG_ASSIGN_OR_RAISE(auto entry, from_json(entry_json)); |
258 | | - list.emplace_back(std::move(entry)); |
259 | | - } |
260 | | - } |
261 | | - return list; |
262 | | -} |
263 | | - |
264 | | -/// \brief Parse a list of items from a JSON object. |
265 | | -/// |
266 | | -/// \param[in] json The JSON object to parse. |
267 | | -/// \param[in] key The key to parse. |
268 | | -/// \param[in] from_json The function to parse an item from a JSON object. |
269 | | -/// \return The list of items. |
270 | | -template <typename T> |
271 | | -Result<std::vector<std::shared_ptr<T>>> FromJsonList( |
272 | | - const nlohmann::json& json, std::string_view key, |
273 | | - const std::function<Result<std::shared_ptr<T>>(const nlohmann::json&)>& from_json) { |
274 | | - std::vector<std::shared_ptr<T>> list{}; |
275 | | - if (json.contains(key)) { |
276 | | - ICEBERG_ASSIGN_OR_RAISE(auto list_json, GetJsonValue<nlohmann::json>(json, key)); |
277 | | - if (!list_json.is_array()) { |
278 | | - return JsonParseError("Cannot parse '{}' from non-array: {}", key, |
279 | | - SafeDumpJson(list_json)); |
280 | | - } |
281 | | - for (const auto& entry_json : list_json) { |
282 | | - ICEBERG_ASSIGN_OR_RAISE(auto entry, from_json(entry_json)); |
283 | | - list.emplace_back(std::move(entry)); |
284 | | - } |
285 | | - } |
286 | | - return list; |
287 | | -} |
288 | | - |
289 | | -/// \brief Convert a map of type <std::string, T> to a json object. |
290 | | -/// |
291 | | -/// Note that ToJson(const T&) is required for this function to work. |
292 | | -template <typename T> |
293 | | -nlohmann::json::object_t ToJsonMap(const std::unordered_map<std::string, T>& map) { |
294 | | - return std::accumulate(map.cbegin(), map.cend(), nlohmann::json::object(), |
295 | | - [](nlohmann::json::object_t obj, const auto& item) { |
296 | | - obj[item.first] = ToJson(item.second); |
297 | | - return obj; |
298 | | - }); |
299 | | -} |
300 | | - |
301 | | -/// \brief Overload of the above function for a map of type <std::string, |
302 | | -/// std::shared_ptr<T>>. |
303 | | -template <typename T> |
304 | | -nlohmann::json::object_t ToJsonMap( |
305 | | - const std::unordered_map<std::string, std::shared_ptr<T>>& map) { |
306 | | - return std::accumulate(map.cbegin(), map.cend(), nlohmann::json::object(), |
307 | | - [](nlohmann::json::object_t obj, const auto& item) { |
308 | | - obj[item.first] = ToJson(*item.second); |
309 | | - return obj; |
310 | | - }); |
311 | | -} |
312 | | - |
313 | | -/// \brief Parse a map of type <std::string, T> from a JSON object. |
314 | | -/// |
315 | | -/// \param[in] json The JSON object to parse. |
316 | | -/// \param[in] key The key to parse. |
317 | | -/// \param[in] from_json The function to parse an item from a JSON object. |
318 | | -/// \return The map of items. |
319 | | -template <typename T = std::string> |
320 | | -Result<std::unordered_map<std::string, T>> FromJsonMap( |
321 | | - const nlohmann::json& json, std::string_view key, |
322 | | - const std::function<Result<T>(const nlohmann::json&)>& from_json = |
323 | | - [](const nlohmann::json& json) -> Result<T> { |
324 | | - static_assert(std::is_same_v<T, std::string>, "T must be std::string"); |
325 | | - try { |
326 | | - return json.get<std::string>(); |
327 | | - } catch (const std::exception& ex) { |
328 | | - return JsonParseError("Cannot parse {} to a string value: {}", SafeDumpJson(json), |
329 | | - ex.what()); |
330 | | - } |
331 | | - }) { |
332 | | - std::unordered_map<std::string, T> map{}; |
333 | | - if (json.contains(key)) { |
334 | | - ICEBERG_ASSIGN_OR_RAISE(auto map_json, GetJsonValue<nlohmann::json>(json, key)); |
335 | | - if (!map_json.is_object()) { |
336 | | - return JsonParseError("Cannot parse '{}' from non-object: {}", key, |
337 | | - SafeDumpJson(map_json)); |
338 | | - } |
339 | | - for (const auto& [key, value] : map_json.items()) { |
340 | | - ICEBERG_ASSIGN_OR_RAISE(auto entry, from_json(value)); |
341 | | - map[key] = std::move(entry); |
342 | | - } |
343 | | - } |
344 | | - return map; |
345 | | -} |
346 | | - |
347 | 169 | } // namespace |
348 | 170 |
|
349 | 171 | nlohmann::json ToJson(const SortField& sort_field) { |
|
0 commit comments