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