24#include <nlohmann/json.hpp>
26#include "iceberg/result.h"
27#include "iceberg/util/macros.h"
35void SetOptionalField(nlohmann::json& json, std::string_view key,
36 const std::optional<T>& value) {
37 if (value.has_value()) {
43 requires requires(
const T& t) { t.empty(); }
44void SetContainerField(nlohmann::json& json, std::string_view key,
const T& value) {
50inline void SetOptionalStringField(nlohmann::json& json, std::string_view key,
51 const std::string& value) {
57inline std::string SafeDumpJson(
const nlohmann::json& json) {
58 return json.dump(-1,
' ',
false,
59 nlohmann::detail::error_handler_t::ignore);
63Result<T> GetTypedJsonValue(
const nlohmann::json& json) {
66 }
catch (
const std::exception& ex) {
67 return JsonParseError(
"Failed to parse {}: {}", SafeDumpJson(json), ex.what());
72Result<T> GetJsonValueImpl(
const nlohmann::json& json, std::string_view key) {
74 return json.at(key).get<T>();
75 }
catch (
const std::exception& ex) {
76 return JsonParseError(
"Failed to parse '{}' from {}: {}", key, SafeDumpJson(json),
82Result<std::optional<T>> GetJsonValueOptional(
const nlohmann::json& json,
83 std::string_view key) {
84 if (!json.contains(key) || json.at(key).is_null()) {
87 ICEBERG_ASSIGN_OR_RAISE(
auto value, GetJsonValueImpl<T>(json, key));
88 return std::optional<T>(std::move(value));
92Result<T> GetJsonValue(
const nlohmann::json& json, std::string_view key) {
93 if (!json.contains(key) || json.at(key).is_null()) {
94 return JsonParseError(
"Missing '{}' in {}", key, SafeDumpJson(json));
96 return GetJsonValueImpl<T>(json, key);
100Result<T> GetJsonValueOrDefault(
const nlohmann::json& json, std::string_view key,
101 T default_value = T{}) {
102 if (!json.contains(key) || json.at(key).is_null()) {
103 return default_value;
105 return GetJsonValueImpl<T>(json, key);
113 return std::accumulate(
list.cbegin(),
list.cend(), nlohmann::json::array(),
114 [](nlohmann::json::array_t arr,
const T& item) {
115 arr.push_back(ToJson(item));
123 return std::accumulate(
list.cbegin(),
list.cend(), nlohmann::json::array(),
124 [](nlohmann::json::array_t arr,
const std::shared_ptr<T>& item) {
125 arr.push_back(ToJson(*item));
138 const nlohmann::json& json, std::string_view key,
139 const std::function<Result<T>(
const nlohmann::json&)>& from_json) {
140 std::vector<T>
list{};
141 if (json.contains(key)) {
142 ICEBERG_ASSIGN_OR_RAISE(
auto list_json, GetJsonValue<nlohmann::json>(json, key));
143 if (!list_json.is_array()) {
144 return JsonParseError(
"Cannot parse '{}' from non-array: {}", key,
145 SafeDumpJson(list_json));
147 for (
const auto& entry_json : list_json) {
148 ICEBERG_ASSIGN_OR_RAISE(
auto entry, from_json(entry_json));
149 list.emplace_back(std::move(entry));
163 const nlohmann::json& json, std::string_view key,
164 const std::function<Result<std::shared_ptr<T>>(
const nlohmann::json&)>& from_json) {
165 std::vector<std::shared_ptr<T>>
list{};
166 if (json.contains(key)) {
167 ICEBERG_ASSIGN_OR_RAISE(
auto list_json, GetJsonValue<nlohmann::json>(json, key));
168 if (!list_json.is_array()) {
169 return JsonParseError(
"Cannot parse '{}' from non-array: {}", key,
170 SafeDumpJson(list_json));
172 for (
const auto& entry_json : list_json) {
173 ICEBERG_ASSIGN_OR_RAISE(
auto entry, from_json(entry_json));
174 list.emplace_back(std::move(entry));
184nlohmann::json::object_t
ToJsonMap(
const std::unordered_map<std::string, T>&
map) {
185 return std::accumulate(
map.cbegin(),
map.cend(), nlohmann::json::object(),
186 [](nlohmann::json::object_t obj,
const auto& item) {
187 obj[item.first] = ToJson(item.second);
196 const std::unordered_map<std::string, std::shared_ptr<T>>&
map) {
197 return std::accumulate(
map.cbegin(),
map.cend(), nlohmann::json::object(),
198 [](nlohmann::json::object_t obj,
const auto& item) {
199 obj[item.first] = ToJson(*item.second);
210template <
typename T = std::
string>
212 const nlohmann::json& json, std::string_view key,
213 const std::function<Result<T>(
const nlohmann::json&)>& from_json =
214 [](
const nlohmann::json& json) -> Result<T> {
215 static_assert(std::is_same_v<T, std::string>,
"T must be std::string");
217 return json.get<std::string>();
218 }
catch (
const std::exception& ex) {
219 return JsonParseError(
"Cannot parse {} to a string value: {}", SafeDumpJson(json),
223 std::unordered_map<std::string, T>
map{};
224 if (json.contains(key)) {
225 ICEBERG_ASSIGN_OR_RAISE(
auto map_json, GetJsonValue<nlohmann::json>(json, key));
226 if (!map_json.is_object()) {
227 return JsonParseError(
"Cannot parse '{}' from non-object: {}", key,
228 SafeDumpJson(map_json));
230 for (
const auto& [key, value] : map_json.items()) {
231 ICEBERG_ASSIGN_OR_RAISE(
auto entry, from_json(value));
232 map[key] = std::move(entry);
std::shared_ptr< MapType > map(SchemaField key, SchemaField value)
Create a MapType with the given key and value fields.
Definition type.cc:388
std::shared_ptr< ListType > list(SchemaField element)
Create a ListType with the given element field.
Definition type.cc:392
Result< std::vector< T > > FromJsonList(const nlohmann::json &json, std::string_view key, const std::function< Result< T >(const nlohmann::json &)> &from_json)
Parse a list of items from a JSON object.
Definition json_util_internal.h:137
nlohmann::json::array_t ToJsonList(const std::vector< T > &list)
Convert a list of items to a json array.
Definition json_util_internal.h:112
nlohmann::json::object_t ToJsonMap(const std::unordered_map< std::string, T > &map)
Convert a map of type <std::string, T> to a json object.
Definition json_util_internal.h:184
Result< std::unordered_map< std::string, T > > FromJsonMap(const nlohmann::json &json, std::string_view key, const std::function< Result< T >(const nlohmann::json &)> &from_json=[](const nlohmann::json &json) -> Result< T > { static_assert(std::is_same_v< T, std::string >, "T must be std::string");try { return json.get< std::string >();} catch(const std::exception &ex) { return JsonParseError("Cannot parse {} to a string value: {}", SafeDumpJson(json), ex.what());} })
Parse a map of type <std::string, T> from a JSON object.
Definition json_util_internal.h:211