diff --git a/restdocs-api-spec/src/main/kotlin/com/epages/restdocs/apispec/ConstrainedFields.kt b/restdocs-api-spec/src/main/kotlin/com/epages/restdocs/apispec/ConstrainedFields.kt index f0518daf..224932c4 100644 --- a/restdocs-api-spec/src/main/kotlin/com/epages/restdocs/apispec/ConstrainedFields.kt +++ b/restdocs-api-spec/src/main/kotlin/com/epages/restdocs/apispec/ConstrainedFields.kt @@ -18,7 +18,7 @@ class ConstrainedFields(private val classHoldingConstraints: Class<*>) { * @param path json path of the field */ fun withPath(path: String): FieldDescriptor = - withMappedPath(path, path) + withMappedPath(path, beanPropertyNameFromPath(path)) /** * @@ -38,7 +38,10 @@ class ConstrainedFields(private val classHoldingConstraints: Class<*>) { .value(this.validatorConstraintResolver.resolveForProperty(beanPropertyName, classHoldingConstraints)) ) + private fun beanPropertyNameFromPath(jsonPath: String) = jsonPath.substringAfterLast(DOT_NOTATION_DELIMITER) + companion object { private const val CONSTRAINTS_KEY = "validationConstraints" + private const val DOT_NOTATION_DELIMITER = "." } } diff --git a/restdocs-api-spec/src/test/kotlin/com/epages/restdocs/apispec/ConstrainedFieldsTest.kt b/restdocs-api-spec/src/test/kotlin/com/epages/restdocs/apispec/ConstrainedFieldsTest.kt index 4a9a25f0..00f3ca09 100644 --- a/restdocs-api-spec/src/test/kotlin/com/epages/restdocs/apispec/ConstrainedFieldsTest.kt +++ b/restdocs-api-spec/src/test/kotlin/com/epages/restdocs/apispec/ConstrainedFieldsTest.kt @@ -7,11 +7,10 @@ import javax.validation.constraints.NotEmpty internal class ConstrainedFieldsTest { - val fields = ConstrainedFields(SomeWithConstraints::class.java) - @Test @Suppress("UNCHECKED_CAST") fun `should resolve constraints`() { + val fields = ConstrainedFields(SomeWithConstraints::class.java) val descriptor = fields.withPath("nonEmpty") then(descriptor.attributes).containsKey("validationConstraints") @@ -19,8 +18,32 @@ internal class ConstrainedFieldsTest { .containsExactly(NotEmpty::class.java.name) } + @Test + @Suppress("UNCHECKED_CAST") + fun `should resolve one level nested constraints`() { + val fields = ConstrainedFields(SomeWithConstraints::class.java) + val descriptor = fields.withPath("nested.nonEmpty") + + then(descriptor.attributes).containsKey("validationConstraints") + then((descriptor.attributes["validationConstraints"] as List).map { it.name }) + .containsExactly(NotEmpty::class.java.name) + } + + @Test + @Suppress("UNCHECKED_CAST") + fun `should resolve two level nested constraints`() { + val fields = ConstrainedFields(SomeWithConstraints::class.java) + val descriptor = fields.withPath("nested.nested.nonEmpty") + + then(descriptor.attributes).containsKey("validationConstraints") + then((descriptor.attributes["validationConstraints"] as List).map { it.name }) + .containsExactly(NotEmpty::class.java.name) + } + private data class SomeWithConstraints( @field:NotEmpty - val nonEmpty: String + val nonEmpty: String, + + val nested: SomeWithConstraints? ) }