diff --git a/code/json/marshaling.hxx b/code/json/marshaling.hxx index f58cdee..4a2d395 100644 --- a/code/json/marshaling.hxx +++ b/code/json/marshaling.hxx @@ -68,11 +68,27 @@ namespace code::json }; - template + template> + struct has_validator + : std::false_type + {}; + + template + struct has_validator< + T, + std::void_t< + decltype(std::declval().validate(std::declval())) + > + > + : std::true_type + {}; + + template struct member_t { using T = member_traits::class_type; using M = member_traits::member_type; + using V = Validator; static constexpr bool is_optional{ is_optional_v @@ -97,7 +113,13 @@ namespace code::json throw std::runtime_error{"missing field '" + Name.str() + "'"}; } - instance.*Member = marshaling_traits::unmarshal(v.get(Name), context); + M value = marshaling_traits::unmarshal(v.get(Name), context); + + if constexpr (!std::is_same_v) { + V::validate(value, context); + } + + instance.*Member = std::move(value); } struct pointer_t @@ -133,7 +155,13 @@ namespace code::json throw std::runtime_error{ "missing field '" + to_string(ptr()) + "'" }; } - instance.*Member = marshaling_traits::unmarshal(*ptr_v, context); + M value = marshaling_traits::unmarshal(*ptr_v, context); + + if constexpr (!std::is_same_v) { + V::validate(value, context); + } + + instance.*Member = std::move(value); } }; @@ -168,6 +196,10 @@ namespace code::json { First::unmarshal(instance, v, context); ((Members::unmarshal(instance, v, context)), ...); + + if constexpr (has_validator::value) { + instance.validate(context); + } } static @@ -209,6 +241,10 @@ namespace code::json ((Bases::json::do_unmarshal(instance, v, context)), ...); First::unmarshal(instance, v, context); ((Members::unmarshal(instance, v, context)), ...); + + if constexpr (has_validator::value) { + instance.validate(context); + } } static