Notre API REST reçoit des entrées d'objets JSON dans lesquelles certains champs doivent être non nuls. Celles-ci peuvent être soit String/Integer, voire même une autre instance de classe comme référence.
Nous essayons de trouver un moyen de faire en sorte que ces champs ne soient pas nuls, au lieu de la méthode correcte pour le contrôle nul dans l'api .
if (myObject.getSomeOtherObject () == null) jette new SomeException ();
Ce que nous voulons avoir est quelque chose comme:
class MyObject { @Champs obligatoires OtherObject someOtherObject; ... }
Nous avons essayé 3 choses:
Passez à jackson 2.0.6 et utilisez les annotations Com.fasterxml.jackson.annotation.JsonProperty Mais cela ne semble tout simplement pas fonctionner. A trouvé ces références: http://jira.codehaus.org/browse/JACKSON-767
Étendre JsonDeserializer pour qu'il vérifie la valeur NULL, mais le problème est qu'il n'est même pas exécuté sur l'entrée NULL.
Classe publique NotNullDeserializer <T> étend JsonDeserializer <T> { @Passer outre la désérialisation publique T (JsonParser jsonparser, DeserializationContext deserializationcontext) lève l'exception IOException, JsonProcessingException { ParameterizedType superClass = (ParameterizedType) getClass (). GetGenericSuperclass (); Type de classe = (Classe) superClass.getActualTypeArguments () [0]; T t = jsonparser.readValueAs (type); if (t == null) { String classNameField = type.getName (); Champ de chaîne = jsonparser.getCurrentName (); lance une nouvelle exception WrongInputException ("Le champ '" + champ + "' de type '" + classNameField + "' ne doit pas être null."); } retourne t; } } La classe publique NotNullAddressDeserializer étend NotNullDeserializer <Address> { } @JsonDeserialize (using = NotNullAddressDeserializer.class) Adressé à;
La classe privée Filter implémente ResourceFilter, ContainerRequestFilter { private final ArrayList requiredParameters; Filtre protégé () { requiredParameters = null; } Filtre protégé (ArrayList requiredParameters) { this.requiredParameters = requiredParameters; } @Passer outre public ContainerRequestFilter getRequestFilter () { retournez ceci; } @Passer outre public ContainerResponseFilter getResponseFilter () { retourne null; } @Passer outre filtre public ContainerRequest (demande ContainerRequest) { if (requiredParameters! = null && requiredParameters.size ()> 0) { MultivaluedMap params = request.getQueryParameters (); params.putAll (request.getFormParameters ()); StringBuffer missingParams = new StringBuffer (); for (String reqParam: requiredParameters) { Liste paramValues = params.get (reqParam); if (paramValues == null || paramValues! = null && paramValues.size () == 0) missingParams.append (reqParam + ","); } if (missingParams.length ()> 0) lance une nouvelle WrongInputException ("Les paramètres requis sont manquants:" + missingParams); } demande de retour; } }
Toute aide et idées appréciées.
JAX-RS sépare assez bien la désérialisation de la validation, c'est-à-dire que Jackson n'a par conception aucun mécanisme pour imposer des valeurs à non-null
, etc. À la place, vous pouvez utiliser BeanValidation pour cela:
javax.validation:validation-api
dans la portée provided
.javax.validation.constraints.NotNull
à votre champ.Pour plus de détails, allez ici .
Vous pouvez utiliser JSON-SCHEMA comme vous pouvez exprimer de nombreuses contraintes sur les champs JSON avec: http://json-schema.org/
Ensuite, vous pouvez générer à partir du schéma vos classes Java avec les annotations @NotNull JSR 303 et utiliser la validation de bean sur votre objet. Cela fonctionne avec Jackson en natif, vous ne devriez donc pas avoir de problème.
Par exemple, vous pouvez utiliser le plugin maven pour le faire: http://wiki.jsonschema2pojo.googlecode.com/git/site/0.3.7/generate-mojo.html
@Required
est une annotation de structure Spring pour les beans injectés, je vous conseille donc de ne pas l'utiliser à cette fin.
Vous pouvez utiliser celui-ci à la place:
http://robaustin.wikidot.com/annotations-and-notnull
@NotNull
String myString;
Pour les contrôles d'exécution, essayez http://code.google.com/p/notnullcheckweaver/
Vous pouvez appliquer la validation not null
en utilisant une combinaison de la bibliothèque Jackson JSON et du javax.validation
avec le package de validation Hibernate.
Si vous utilisez Maven, voici les dépendances que vous pouvez utiliser:
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
</dependencies>
Ensuite, votre code devra convertir certains JSON en votre objet annoté et vous devrez valider l'objet à l'aide de javax.validation.Validator
. Voici un exemple de code démontrant comment cela peut être effectué (voir la méthode validate
correspondante):
public class ShareLocationService {
private ObjectMapper mapper = new ObjectMapper();
private ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
// Materialize the Java object which contains the validation annotations
public ShareLocation readFrom(String json) throws IOException {
return mapper.readerFor(ShareLocation.class).readValue(json);
}
// validate and collect the set of validations
public Set<String> validate(String json) throws IOException {
ShareLocation shareMyLocation = readFrom(json);
Validator validator = factory.getValidator();
Set<ConstraintViolation<ShareLocation>> violations = validator.validate(shareMyLocation);
return violations.stream().map(Object::toString).collect(Collectors.toSet());
}
}
Voici un exemple de classe utilisant les annotations de validation:
public class ShareLocation {
@JsonProperty("Source")
@NotNull
private String source;
@JsonProperty("CompanyCode")
private String companyCode;
@JsonProperty("FirstName")
private String firstName;
@JsonProperty("LastName")
private String lastName;
@JsonProperty("Email")
private String email;
@JsonProperty("MobileNumber")
private String mobileNumber;
@JsonProperty("Latitude")
@NotNull
private Double latitude;
@JsonProperty("Longitude")
@NotNull
private Double longitude;
@JsonProperty("LocationDateTime")
@NotNull
private String locationDateTime;