Closed beached closed 2 years ago
@wxprospero This is a design issue, but a quick work around would be https://jsonlink.godbolt.org/z/Wz6dednWb where the nullable type concept is specialized for the type. I have a fix in mind as I think the design is wrong here but I need to investigate more.
#include <daw/json/daw_json_iterator.h>
#include <daw/json/daw_json_link.h>
#include <iostream>
#include <unordered_map>
struct PersonObject {
int id{};
std::string name;
std::unordered_map<std::string, std::string> fields;
};
namespace daw::json {
namespace concepts {
template <typename K, typename V, typename... Ts>
struct nullable_value_traits<std::unordered_map<K, V, Ts...>> {
using value_type = std::unordered_map<K, V, Ts...>;
using nullable_type = std::unordered_map<K, V, Ts...>;
static constexpr bool is_nullable = true;
static constexpr value_type const &read(nullable_type const &val) {
return *val;
}
constexpr nullable_type operator()(construct_nullable_with_value_t,
nullable_type const &opt) const
noexcept(std::is_nothrow_copy_constructible_v<nullable_type>) {
return opt;
}
constexpr nullable_type operator()(construct_nullable_with_value_t,
nullable_type &&opt) const
noexcept(std::is_nothrow_move_constructible_v<nullable_type>) {
return opt;
}
template <
typename... Args,
std::enable_if_t<nullable_impl::is_nullable_value_type_constructible_v<
value_type, Args...>,
std::nullptr_t> = nullptr>
constexpr nullable_type operator()(construct_nullable_with_value_t,
Args &&...args) const
noexcept(std::is_nothrow_constructible_v<value_type, Args...>) {
return nullable_type(DAW_FWD(args)...);
}
constexpr nullable_type operator()(
construct_nullable_with_empty_t) const noexcept {
return nullable_type();
}
static constexpr bool has_value(nullable_type const &val) {
return true;
}
};
} // namespace concepts
template <>
struct json_data_contract<PersonObject> {
static constexpr char const id[] = "id";
static constexpr char const name[] = "name";
static constexpr char const fields[] = "fields";
using type = json_member_list<
json_number<id, int>, json_string<name>,
json_key_value_null<
fields, std::unordered_map<std::string, std::string>, std::string>>;
};
} // namespace daw::json
int main() {
std::string raw_json{R"_(
{
"id": 10,
"name": "Jason",
"fields": {"city": "Chicago", "Title": "Manager"},
}
)_"};
PersonObject person = daw::json::from_json<PersonObject>(raw_json);
return 0;
}
The docs briefly talk to it here. https://github.com/beached/daw_json_link/blob/release/docs/cookbook/nullable_value_concept.md
I want to take this so default constructible things work here but not for the type deduction when using json_link<"name", type_t>
like mappings or eleswhere(arrays)
Thanks
Thanks for reporting this, I believe the patch fixes it. Was able to find the issue and remediate.
@wxprospero While you're here, is "json_key_value_null" broken as well? Why does changing "json_key_value" to "json_key_value_null" break this, whereas with other types (like json_number or json_string), changing it to nullable requires no extra or change to template parameters? An unordered_map is default constructable, and value initializable, isn't it?
There is also no documentation for how to use json_key_value_null, that I can find
_Originally posted by @wxprospero in https://github.com/beached/daw_json_link/issues/334#issuecomment-1299461940_