2017-04-04 6 views
3

Je consomme une API REST avec RestTemplate. La réponse que je reçois de l'API contient beaucoup d'objets imbriqués. Voici un petit extrait comme exemple:CustomDeserializer n'a pas de constructeur par défaut (no arg)

"formularios": [ 
    { 
    "form_data_id": "123006", 
    "form_data": { 
     "form_data_id": "123006", 
     "form_id": "111", 
     "efs": { 
     "1": {}, 
     "2": "{\"t\":\"c\",\"st\":\"m\",\"v\":[{\"id\":\"3675\",\"l\":\"a) Just an example\",\"v\":\"1\"},{\"id\":\"3676\",\"l\":\"b) Another example.\",\"v\":\"2\"}]}" 
     } 
    } 

Le problème que je vais avoir est que la plupart du temps le « 1 » a effectivement contenu, tout comme « 2 », et le jackson juste parse comme une chaîne sur l'objet "efs". Mais parfois, tout comme dans l'extrait de code, l'API l'envoie vide, et jackson le prend comme objet, ce qui me donne une erreur qui dit quelque chose à propos de START_OBJECT (je ne me souviens pas de l'erreur exacte, mais ce n'est pas important pour cette question).

J'ai donc décidé de créer un désérialisateur personnalisé, donc quand jackson lit "1", il ignore l'objet vide et le traite comme une chaîne vide.

Voici mon désérialiseur personnalisé:

public class CustomDeserializer extends StdDeserializer<Efs> { 

public CustomDeserializer(Class<Efs> t) { 
    super(t); 
} 

@Override 
public Efs deserialize(JsonParser jp, DeserializationContext dc) 
     throws IOException, JsonProcessingException { 

    String string1 = null; 
    String string2 = null; 
    JsonToken currentToken = null; 

    while ((currentToken = jp.nextValue()) != null) { 
     if (currentToken.equals(JsonToken.VALUE_STRING)) { 
      if (jp.getCurrentName().equals("1")) { 
       string1 = jp.getValueAsString(); 
      } else { 
       string2 = jp.getValueAsString(); 
      } 

     } else { 
      if (jp.getCurrentName().equals("2")) { 
       string2 = jp.getValueAsString(); 
      } 

     } 
    } 
    return new Efs(string1, string2); 

    } 
} 

Et c'est la façon dont je l'utilise lors de la réception de la réponse de l'API:

ObjectMapper mapper = new ObjectMapper(); 
    SimpleModule mod = new SimpleModule("EfsModule"); 
    mod.addDeserializer(Efs.class, new CustomDeserializer(Efs.class)); 
    mapper.registerModule(mod); 


    List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); 
    MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter(); 
    jsonMessageConverter.setObjectMapper(mapper); 
    messageConverters.add(jsonMessageConverter); 


    RestTemplate restTemplate = new RestTemplate(); 
    restTemplate.setMessageConverters(messageConverters); 

Je reçois l'erreur:

CustomDeserializer has no default (no arg) constructor 

Mais je ne sais pas exactement ce que je fais mal et comment le résoudre. Merci pour l'aide et les excuses pour la longue question, je voulais donner le plus de contexte possible.

Répondre

5

Vous devez posséder un constructeur par défaut sans arguments. Ce que vous pouvez faire est de créer un (ou remplacer l'autre si vous ne avez pas vraiment besoin):

public class CustomDeserializer extends StdDeserializer<Efs> { 

    public CustomDeserializer() { 
     super(Efs.class); 
    } 
    ... 
} 
+0

Oh wow haha ​​je me sens stupide, mais oui, il a travaillé, merci. – abril