web-dev-qa-db-fra.com

Appliquer un champ non nul dans un objet JSON

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é à;

  • Écrire notre propre annotation @Required et essayer de vérifier avec ResourceFilter, mais il semble que je ne puisse pas obtenir l'objet réel à partir de ContainerRequest et même si nous le pouvions, nous ne savions pas comment exécuter une vérification approfondie de la référence null dans object.otherObject.someObject.fieldNotNullable

 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.

19
urir

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:

  1. Ajoutez une dépendance à javax.validation:validation-api dans la portée provided.
  2. Ajoutez l'annotation javax.validation.constraints.NotNull à votre champ.

Pour plus de détails, allez ici .

23
rü-

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

2
zenbeni

@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/

1
Adam Adamaszek

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;
0
gil.fernandes