making/yavi

Is it possible to validate lists Strings

jadlr opened this issue · 2 comments

jadlr commented

Hi, thanks a ton for this lib! Not sure if it's ok to open an issue with a question, but I saw there is a label for questions, so I thought I'd give it a shot.

I'm trying to validate a list of String using the kotlin api, but I cannot figure out how to get to to work:

data class User(val name: String, val nicknames: List<String>)

val userValidator = validator<User> {
    User::name {
        notBlank()
        lessThanOrEqual(32)
    }
    User::nicknames forEach {
        notBlank()
        lessThanOrEqual(32)
    }
}

This does not compile. Is there a way to get this to work? Thanks!

@jadlr Questions here are welcome as YAVI does not have a large community.

Java code equivalent to the above is like

Validator<User> validator = ValidatorBuilder.<User>of()
		.constraint(User::getName, "name", c -> c.notBlank().lessThanOrEqual(32))
		.forEach(User::getNicknames, "nicknames", c -> c._string(String::toString, "", n -> n.notBlank().lessThanOrEqual(32)))
		.build();

The Kotlin DSL only accepts KProperty1. KProperty1 is needed to automatically fill the constarint name.
Unfortunately String::toString is not a KProperty1, so the bellow code does not work like Java code

val validator = validator<User> {
	User::name {
		notBlank()
		lessThanOrEqual(32)
	}
	User::nicknames forEach {
		String::toString {
			notBlank()
			lessThanOrEqual(32)
		}
	}
}

while the bellow will work as String::length is a KProperty1

val validator = validator<User> {
	User::name {
		notBlank()
		lessThanOrEqual(32)
	}
	User::nicknames forEach {
		String::length {
			greaterThan(0)
			lessThanOrEqual(32)
		}
	}
}

What YAVI expects when it has a collection constraint is an element of value object type rather than a String.
So the following will work perfectlly

data class Name(val value: String)
data class User(val name: String, val nicknames: List<Name>)

val validator = validator<User> {
	User::name {
		notBlank()
		lessThanOrEqual(32)
	}
	User::nicknames forEach {
		Name::value {
			notBlank()
			lessThanOrEqual(32)
		}
	}
}

Or you can still write code that is completely Java equivalent, without using the DSL:

val validator = ValidatorBuilder.of<User>()
	.constraint(User::name, "name") {
		it.notBlank().lessThan(32)
	}
	.forEach(User::nicknames, "nicknames") { c ->
		c.constraint(String::toString, "") {
			it.notBlank().lessThanOrEqual(32)
		}
	}
	.build()
jadlr commented

Thanks a ton for the quick reply! That helps a lot 👍