2017-09-24 4 views
1

Nous utilisons le mappeur Jackson JSON dans notre code pour désérialiser certains objets de configuration. Nous aimerions que Jackson échouer sur désérialisation lorsque les champs spécifiques sont manquants ou videsJackson Mapper - comment échouer sur des valeurs nulles ou vides

La seule fonctionnalité de Jackson pour soutenir ce comportement est pour les primitives:

final DeserializationConfig.Feature failOnPremitives = DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES; 

La chose est les champs en question sont principalement des chaînes

Toute aide est très appréciée

Répondre

0

Il y a une option appelée: FAIL_ON_NULL_FOR_CREATOR_PARAMETERS.

je suppose qu'il serait accessible à: DeserializationConfig.Feature.FAIL_ON_NULL_FOR_CREATOR_PARAMETERS;

Ou dans yml:

jackson: 
    serialization: 
     indent-output: false 
    deserialization: 
     fail-on-unknown-properties: true 
     fail-on-missing-creator-properties: true 
     fail-on-null-creator-properties: true 

Cela fonctionne sur tous les types, cordes, ints, doubles etc ..

+0

Ne fonctionne-t-il pas uniquement pour les propriétés liées aux paramètres d'une méthode de création? Je veux dire un constructeur ou une méthode d'usine statique. –

+0

@CassioMazzochiMolin Je suppose que oui, mais ce n'est pas vraiment un problème. –

0

Avez-vous envisagé Bean Validation? Alors que Jackson se concentre sur l'analyse JSON, Bean Validation consiste à déclarer et à effectuer une validation sur vos beans.

Vous pouvez utiliser @NotNull ou @NotBlank à partir de Hibernate Validator, l'implémentation de référence Bean Validation.


Vous pouvez également utiliser JSON Schema.

0

Un désérialiseur personnalisé spécifique à l'objet devrait être créé.

import com.fasterxml.jackson.core.JsonParser; 
import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.core.ObjectCodec; 
import com.fasterxml.jackson.core.Version; 
import com.fasterxml.jackson.databind.DeserializationContext; 
import com.fasterxml.jackson.databind.JsonNode; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 
import com.fasterxml.jackson.databind.module.SimpleModule; 

import java.io.IOException; 

class JacksonDeserializerTest { 

    public static void main(String[] args) throws Exception { 
     ObjectMapper mapper = new ObjectMapper(); 
     SimpleModule module = new SimpleModule("CustomPersonDeserializer", new Version(1, 0, 0, null, null, null)); 
     module.addDeserializer(Person.class, new CustomPersonDeserializer()); 
     mapper.registerModule(module); 

     String jsonString = "{ \"id\": 1, \"name\": \"User 1 \"}"; 
     Person user = mapper.readValue(jsonString, Person.class); 
     System.out.println("User: " + user.toString()); 

     jsonString = "{ \"id\": 1}"; 
     user = mapper.readValue(jsonString, Person.class); 
    } 

    static class CustomPersonDeserializer extends StdDeserializer<Person> { 

     private static final long serialVersionUID = -4100181951833318756L; 

     public CustomPersonDeserializer() { 
      this(null); 
     } 

     public CustomPersonDeserializer(Class<?> vc) { 
      super(vc); 
     } 

     @Override 
     public Person deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException, JsonProcessingException { 
      Person person = new Person(); 
      ObjectCodec codec = parser.getCodec(); 
      JsonNode node = codec.readTree(parser); 

      JsonNode idNode = node.get("id"); 
      int id = idNode.asInt(); 
      person.setId(id); 

      JsonNode nameNode = node.get("name"); 
      if(nameNode == null){ 
       throw new IOException("name must be provided"); 
      } 

      String name = nameNode.asText(); 
      if (name.trim().length() < 1){ 
       throw new IOException("name can not be empty"); 
      } 

      person.setName(name); 
      return person; 
     } 
    } 

    static class Person { 
     private int id; 
     private String name; 

     public String getName() { 
      return name; 
     } 

     public void setName(String name) { 
      this.name = name; 
     } 

     public int getId() { 
      return id; 
     } 

     public void setId(int id) { 
      this.id = id; 
     } 

     @Override 
     public String toString() { 
      return "Person{" + 
        "name='" + name + '\'' + 
        ", id=" + id + 
        '}'; 
     } 
    } 
} 
+0

Sérieusement? ! Souhaitez-vous créer un déserializer personnalisé pour chaque classe? Et si vous aviez des douzaines ou même des centaines de cours? Vous ne prendrez aucun avantage des capacités de Jackson. C'est loin d'être une solution acceptable pour un vrai projet. –

+0

@CassioMazzochiMolin voir ma réponse. –