I have a Spring Boot application using javax.validation
annotations and I'm trying to return friendly JSON error messages pointing to the offending field, yet converting from the available "Java-object" path to either JSONPath or JSON Pointer is something I'm not finding a way to do.
SSCO sample:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.Min;
import java.util.List;
public class Test {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
Data data = new Data();
System.out.println("Serialized: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(data));
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
validator.validate(data).forEach(violation -> {
System.out.println("Path: " + violation.getPropertyPath());
});
}
public static class Data {
@JsonProperty("foobar")
@Valid
public List<Foo> foo = List.of(new Foo());
}
public static class Foo {
@Min(100)
public int barBaz = 42;
}
}
Output:
Serialized: {
"foobar" : [ {
"bar_baz" : 42
} ]
}
Path: foo[0].barBaz
As you can see, I need to convert foo[0].barBaz
into either $.foobar[0].bar_baz
or /foobar/0/bar_baz
. The parsed object (the data
variable above) is also provided by the BindingResult
object that holds the validation information.
I thought about doing some String manipulation, but that's messy, hacky, and can break easily with @JsonProperty
which I would need to handle separately, maybe other corner cases that I didn't think about. Plus, we use SNAKE_CASE
as a standard, changing to simplify the task is not a solution.
I suppose Jackson's ObjectMapper
could be used somehow to make this conversion, or some other piece of Jackson API, but I couldn't find anything about that. Any other library that can do this is also fine (ideally it should understand Jackson annotations like @JsonProperty
).