Add basic model validation after deserialization
This commit is contained in:
parent
cf503e6bfa
commit
5ab48d8c36
@ -68,11 +68,27 @@ namespace code::json
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<member_name_t Name, auto Member>
|
template<typename, typename = std::void_t<>>
|
||||||
|
struct has_validator
|
||||||
|
: std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct has_validator<
|
||||||
|
T,
|
||||||
|
std::void_t<
|
||||||
|
decltype(std::declval<T const&>().validate(std::declval<marshaling_context_t*>()))
|
||||||
|
>
|
||||||
|
>
|
||||||
|
: std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<member_name_t Name, auto Member, typename Validator = void>
|
||||||
struct member_t
|
struct member_t
|
||||||
{
|
{
|
||||||
using T = member_traits<decltype(Member)>::class_type;
|
using T = member_traits<decltype(Member)>::class_type;
|
||||||
using M = member_traits<decltype(Member)>::member_type;
|
using M = member_traits<decltype(Member)>::member_type;
|
||||||
|
using V = Validator;
|
||||||
|
|
||||||
static constexpr bool is_optional{
|
static constexpr bool is_optional{
|
||||||
is_optional_v<M>
|
is_optional_v<M>
|
||||||
@ -97,7 +113,13 @@ namespace code::json
|
|||||||
throw std::runtime_error{"missing field '" + Name.str() + "'"};
|
throw std::runtime_error{"missing field '" + Name.str() + "'"};
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.*Member = marshaling_traits<M>::unmarshal(v.get(Name), context);
|
M value = marshaling_traits<M>::unmarshal(v.get(Name), context);
|
||||||
|
|
||||||
|
if constexpr (!std::is_same_v<V, void>) {
|
||||||
|
V::validate(value, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.*Member = std::move(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pointer_t
|
struct pointer_t
|
||||||
@ -133,7 +155,13 @@ namespace code::json
|
|||||||
throw std::runtime_error{ "missing field '" + to_string(ptr()) + "'" };
|
throw std::runtime_error{ "missing field '" + to_string(ptr()) + "'" };
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.*Member = marshaling_traits<M>::unmarshal(*ptr_v, context);
|
M value = marshaling_traits<M>::unmarshal(*ptr_v, context);
|
||||||
|
|
||||||
|
if constexpr (!std::is_same_v<V, void>) {
|
||||||
|
V::validate(value, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.*Member = std::move(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -168,6 +196,10 @@ namespace code::json
|
|||||||
{
|
{
|
||||||
First::unmarshal(instance, v, context);
|
First::unmarshal(instance, v, context);
|
||||||
((Members::unmarshal(instance, v, context)), ...);
|
((Members::unmarshal(instance, v, context)), ...);
|
||||||
|
|
||||||
|
if constexpr (has_validator<T>::value) {
|
||||||
|
instance.validate(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -209,6 +241,10 @@ namespace code::json
|
|||||||
((Bases::json::do_unmarshal(instance, v, context)), ...);
|
((Bases::json::do_unmarshal(instance, v, context)), ...);
|
||||||
First::unmarshal(instance, v, context);
|
First::unmarshal(instance, v, context);
|
||||||
((Members::unmarshal(instance, v, context)), ...);
|
((Members::unmarshal(instance, v, context)), ...);
|
||||||
|
|
||||||
|
if constexpr (has_validator<T>::value) {
|
||||||
|
instance.validate(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
Loading…
x
Reference in New Issue
Block a user