In my class, there's a field I want to validate, but I don't want to return it in the response. For that I've used the annotations
#Valid
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private User user;
The problem is that when I use WRITE_ONLY, the code doesn't check the validations. What can I do to fix that?
When you are using Spring-Boot, take a look at #Validated.
Related
I have the same form that displays more or less fields depending on the user's role. So I use #JsonView to hide/ignore the fields that are not related to the current user's role. But the validation is still enabled and the #NotNull rule is triggered.
#JsonView({View.Admin.class, View.Tech.class})
#NotNull
private String name;
I would like to find a way to enable or disable some validation annotations for example when the user's role is not administrator.
Is it possible to use these view (View.Admin.class / View.Tech.class) as a group for validation please?
use #JsonIgnore may help you to achieve,because it will ignore the column and validation annotation as well
As stated in the title, I'm using the Validator to validate fields based on their names like this:
mandatoryInputs.stream()
.map(x -> v.validateProperty(accountBenefitForm, x, AccountBenefitFormAdditionalInfo.class))
it works fine, but only for the simple fields like Strings that have their constraints in the accountBenefitForm for example:
#NotBlank(message = "Username can not be null.", groups = {AccountBenefitFormBasicInfo.class})
#Size(max = 255, message = "Username is too long (max size 255).")
private String username;
But it won't work for objects that have multiple fields inside them, like this one:
#Valid
private ContactData contactData;
where ContactData implementation looks like this:
#NotBlank(message = "You have to add e-mail address.", groups = {AccountBenefitFormAdditionalInfo.class})
#Email(message = "E-mail is not valid.", groups = {AccountBenefitFormAdditionalInfo.class})
#Size(max = 255, message = "E-mail is too long (max size 255).", groups = {AccountBenefitFormAdditionalInfo.class})
private String email;
#NotBlank(groups = {AccountBenefitFormAdditionalInfo.class})
private String phoneNumber;
Is there a way I can make this work or do I need to validate those more complex objects on their own?
You have basically two kinds of annotations that can be used for validations here: Spring annotations (#Validated) as well as the javax annotation (#Valid, #NotBlank) etc.
For Spring, you can luckily often skip the manual validation unless you have some custom constraints (e.g. if person lives in country ABC, they need to provide additional info). Annotating just the field is not enough if you don't cascade the validation from the outer class. This cascade can be done conveniently on method-level by annotating the method param with #Valid e.g.
void doSomething(#Valid ContactDataHolder contactDataHolder) { ... }
If you'd like to use validation in Spring, I would recommend to use the Spring Validator interface instead of the one from javax as it should give you the expected behavior for nesting. You might also decide to apply #Validated on the class level to save you from writing #Valid(ated) on the method level each time.
So I've managed to somewhat resolve my problem by using the Apache BVal. Heres the code to create a validator to use the validateProperty method with cascading validation enabled:
ValidatorFactory factory = Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory();
CascadingPropertyValidator validator = factory.getValidator().unwrap(CascadingPropertyValidator.class);
validator.validateProperty(accountBenefitForm, x, true, Default.class, AccountBenefitFormAdditionalInfo.class))
where x is the string of field to validate, and if that field is annotated with #Valid, it will then validate the inside fields according to their own constraints.
Along the way I've also found out that you can just use the "normal" javax Validator and pass the field to validate as contactData.email which means validate email field of the contactData field of the object that u pass as first argument to the validateProperty method.
Edit:
BVal supports Bean Validation 1.1 (JSR 349) and not the 2.0 version(JSR 380), and since #NotBlank or #NotEmpty constrains are part of 2.0, it won't validate a field annotated with them. Here are the docs for the 1.1 , and 2.0
I know how I can make Jackson to ignore any additional fields in Json, simply by adding
#JsonIgnoreProperties(ignoreUnknown = true):
#JsonIgnoreProperties(ignoreUnknown = true)
class MyDto {
int someField;
}
But side-effect of this is that Jackson now also accepts incomplete JSON and fills missing fields with nulls.
How can I enforce Jackson to require every field to exist in json and still ignore additional fields in it?
Thank you.
Jackson explicitly does NOT validate logical POJO contents; instead, you are recommended to use Bean Validation (JSR-303, see http://en.wikipedia.org/wiki/Bean_Validation) API implementation; for example one provided by Hibernate project: http://hibernate.org/validator/
This is the approach many frameworks take; for example, DropWizard supports data-binding using Jackson, and then validation (after data-bind, before business logic run) using Bean Validation.
In order to check if all properties needed are available you need to add the required anotation to the property.
#JsonProperty(value = "response", required = true)
public SomeResponse response;
Does naybody knows a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
Does anybody know a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
E.g. in the following class I want to receive (with POST) values for 'name' and for 'confidential', buy while returning (with GET) I only need 'name' value, not 'confidential'.
#Entity
#Table(name = "a")
#XmlRootElement
#JsonIgnoreProperties({"confifentialInfo"})
public class A extends B implements Serializable {
private String name;
#Basic(optional = false)
private String confifentialInfo;
// more fields, getters and setters
}
If you are using the JAXB approach, you can mark fields with #XmlTransient to omit them. If you are using POJO mapping or want to exclude fields only for some requests, you should construct the JSON with the low level JSON API.
If you are using Jackson, you can use the annotation #JsonIgnore for methods
Marker annotation similar to javax.xml.bind.annotation.XmlTransient
that indicates that the annotated method is to be ignored by
introspection-based serialization and deserialization functionality.
That is, it should not be consider a "getter", "setter" or "creator".
And #JsonIgnoreProperties for properties
Annotation that can be used to either suppress serialization of
properties (during serialization), or ignore processing of JSON
properties read (during deserialization).
I am trying to validate a form using Spring with integrated JSR-303 validations with Hibernate implementation. I have a "confirm email" (emailConf) field that I would like to confirm is equal to the email field. I saw a post of someone doing it like this:
public class ContactInfoForm {
#NotEmpty
private String name;
#NotEmpty
#Email
private String email;
#Expression(value = "emailConf= email", applyIf = "emailConf is not blank")
private String emailConf;
...
}
However, this emailConf validation is not working (i.e. no error occurs when the fields don't match). I've seen a couple tutorials that have shown similar annotations, but can't find them anymore or any documentation on how this works. Does anyone know a way to validate "confirm email/password" fields through annotation? I am currently using the alternative, which is to implement Validator and validate the confirm fields in the validate method.
May you should have look at this question and its answers: there are many ways discussed how to do a such a validation (it is about password and password confirm, but the problem is the same).
What you need is a "Class-level constraint" (as described by JSR-303) if you want to compare 2 field of the same class. I don't think your #Expression will work that way.