@@ -87,7 +87,19 @@ pub enum ValidationErrorKind {
8787 TypeMismatch { expected : String , got : String } ,
8888
8989 /// Missing required property
90- MissingRequiredProperty { property : String } ,
90+ ///
91+ /// When the schema knows what the absent property should have been, the
92+ /// error advertises it, mirroring the message the user would have seen had
93+ /// the property been present with a bad value:
94+ /// - `allowed` carries the permitted values when the subschema is an enum
95+ /// (like [`ValidationErrorKind::InvalidEnumValue`]).
96+ /// - `expected_type` carries the permitted type(s) otherwise (like
97+ /// [`ValidationErrorKind::TypeMismatch`]).
98+ MissingRequiredProperty {
99+ property : String ,
100+ allowed : Option < Vec < String > > ,
101+ expected_type : Option < String > ,
102+ } ,
91103
92104 /// Unknown property in closed object
93105 UnknownProperty { property : String } ,
@@ -176,9 +188,23 @@ impl ValidationErrorKind {
176188 ValidationErrorKind :: TypeMismatch { expected, got } => {
177189 format ! ( "Expected {}, got {}" , expected, got)
178190 }
179- ValidationErrorKind :: MissingRequiredProperty { property } => {
180- format ! ( "Missing required property '{}'" , property)
181- }
191+ ValidationErrorKind :: MissingRequiredProperty {
192+ property,
193+ allowed,
194+ expected_type,
195+ } => match ( allowed, expected_type) {
196+ ( Some ( values) , _) if !values. is_empty ( ) => {
197+ format ! (
198+ "Missing required property '{}' (must be one of: {})" ,
199+ property,
200+ values. join( ", " )
201+ )
202+ }
203+ ( _, Some ( ty) ) => {
204+ format ! ( "Missing required property '{}' (expected {})" , property, ty)
205+ }
206+ _ => format ! ( "Missing required property '{}'" , property) ,
207+ } ,
182208 ValidationErrorKind :: UnknownProperty { property } => {
183209 format ! ( "Unknown property '{}'" , property)
184210 }
@@ -641,6 +667,8 @@ mod tests {
641667 fn test_error_code_missing_required_property ( ) {
642668 let kind = ValidationErrorKind :: MissingRequiredProperty {
643669 property : "foo" . to_string ( ) ,
670+ allowed : None ,
671+ expected_type : None ,
644672 } ;
645673 assert_eq ! ( kind. error_code( ) , "Q-1-10" ) ;
646674 }
@@ -994,6 +1022,8 @@ mod tests {
9941022 let error = ValidationError :: new (
9951023 ValidationErrorKind :: MissingRequiredProperty {
9961024 property : "toc" . to_string ( ) ,
1025+ allowed : None ,
1026+ expected_type : None ,
9971027 } ,
9981028 path,
9991029 ) ;
@@ -1003,6 +1033,30 @@ mod tests {
10031033 ) ;
10041034 }
10051035
1036+ #[ test]
1037+ fn test_missing_required_property_with_allowed_values ( ) {
1038+ let kind = ValidationErrorKind :: MissingRequiredProperty {
1039+ property : "version" . to_string ( ) ,
1040+ allowed : Some ( vec ! [ "0.1.0" . to_string( ) ] ) ,
1041+ expected_type : None ,
1042+ } ;
1043+ assert_eq ! (
1044+ kind. message( ) ,
1045+ "Missing required property 'version' (must be one of: 0.1.0)"
1046+ ) ;
1047+ }
1048+
1049+ #[ test]
1050+ fn test_missing_required_property_empty_allowed_values ( ) {
1051+ // An empty allowed list must not append a "(must be one of: )" clause.
1052+ let kind = ValidationErrorKind :: MissingRequiredProperty {
1053+ property : "version" . to_string ( ) ,
1054+ allowed : Some ( vec ! [ ] ) ,
1055+ expected_type : None ,
1056+ } ;
1057+ assert_eq ! ( kind. message( ) , "Missing required property 'version'" ) ;
1058+ }
1059+
10061060 // Tests for ValidationError::with_schema_path
10071061 #[ test]
10081062 fn test_validation_error_with_schema_path ( ) {
0 commit comments