I don't want to do a null check field by field
You could avoid writing the check yourself but you necessary need to "mark" the constraints on the fields.
For that you could use the Validator API (JSR 380 which Hibernate 6 provides the default implementation) to annotate your class fields with @Null and @NotNull.
And validate the instance explicitly with a Validator.
Note that annotated fields could be as mandatory null in a context and not necessarily null in another. And it is compatible with this way as the validator will validate the object only as it is requested : that is on demand.
According to your comment :
I am working on a codebase and your solution is invasive. I would have
to get my hands on the low level json parser that creates that pojo. I
don't want to do that
In this case you could use a Map external to the current class that you want to validate.
It would allow to maintain the name of the field that you validate and using it in your error message (useful for debugging).
For example :
Foo foo = new Foo();
// set foo fields...
// expected null but was not null
Map<String, Object> hasToBeNullMap = new HashMap<>();
hasToBeNullMap.put("x", foo.getX());
hasToBeNullMap.put("y", foo.getY());
hasToBeNullMap.put("z", foo.getZ());
String errrorMessageForNullExpected = getErrorFieldNames(hasToBeNullMap, Objects::nonNull);
// expected not null but was null
Map<String, Object> hasToBeNotNullMap = new HashMap<>();
hasToBeNotNullMap.put("z", foo.getZ());
String errrorMessageForNotNullExpected = getErrorFieldNames(hasToBeNotNullMap, o -> o == null);
private static String getErrorFieldNames(Map<String, Object> hasToBeNullMap, Predicate<Object> validationPred) {
return hasToBeNullMap.entrySet()
.stream()
.filter(validationPred::test)
.map(Entry::getKey)
.collect(joining(","));
}