web-dev-qa-db-fra.com

Jackson lève JsonMappingException sur désérialiser; demande le constructeur single-String?

Une autre question, mais liée à celle-ci: Désérialisation de JSON avec Jackson - Pourquoi JsonMappingException "Aucun constructeur approprié"?

Cette fois, je reçois une erreur différente, à savoir que le désérialiseur de Jackson se plaint de ne pas avoir de "méthode constructeur/fabrique à une seule chaîne" dans ma classe ProtocolContainer.

Cependant, si j'ajoute un constructeur à chaîne unique, comme ceci:

public ProtocolContainer(String json) {}

l'exception disparaît effectivement, mais la ProtocolContainer que je m'attendais à trouver est "vide", c'est-à-dire que toutes ses propriétés sont dans leur état initial et ne sont pas renseignées selon la chaîne JSON.

Pourquoi donc?

Je suis presque sûr que vous ne devriez pas avoir besoin d'un constructeur à chaîne unique, et si vous faites cela, vous ne devriez pas avoir à renseigner les propriétés de ce constructeur, n'est-ce pas?

=)

11
Ted

Oh, alors encore une fois, j'ai trouvé la réponse APRÈS avoir posté cette question (même si j'ai essayé beaucoup de choses avant de poster).

Pour résoudre ce problème, j'ai utilisé l'annotation @JsonCreator. J'ai simplement annoté ma méthode statique Create, comme ceci:

@JsonCreator
public static ProtocolContainer Create(String jsonString)
{

    ProtocolContainer pc = null;
    try {
        pc = mapper.readValue(jsonString, ProtocolContainer.class);
    } catch (JsonParseException|JsonMappingException|IOException e) {
        // handle
    }

    return pc;
}

Et puis le problème résolu.

19
Ted

L'exception suggère que la valeur JSON que vous avez est une chaîne, quelque chose comme:

{ "protocol" : "http" }

ou peut-être "JSON à double citation":

"\"{\"property\":\"value\"}\"

en essayant de se lier comme:

ProtocolContainer p = mapper.readValue(json, ProtocolContainer.class);

dans ce cas, Jackson n'a aucune propriété à mapper, juste une chaîne. Et dans ce cas, il faut en effet un désérialiseur personnalisé ou une méthode créateur. Les méthodes Creator sont soit des constructeurs à un seul argument, soit des méthodes statiques à une seule chaîne: la différence étant que seuls les constructeurs peuvent être détectés automatiquement (il s'agit simplement d'un raccourci pratique, car il ne peut y avoir qu'un seul méthodes statiques).

Votre solution fonctionne effectivement, je pensais juste que je donnerais un aperçu de ce qui se passait.

En le relisant une deuxième fois, il semble plus probable que vous ayez des éléments à double citation (JSON en JSON): une autre chose à considérer est d'obtenir un JSON simple, si possible. Mais c'est peut-être difficile à faire.

18
StaxMan

J'ai eu le même problème. Pour moi, la solution consistait à passer de la méthode String à la méthode convertValue à une méthode InputStream à la méthode readValue:

// Instead of this:
String jsonString = "..."
ProtocolContainer pc = mapper.convertValue(jsonString, ProtocolContainer.class);

// ... do this:
String jsonString = "..."
InputStream is = new StringInputStream(jsonString);
ProtocolContainer pc = mapper.readValue(is, ProtocolContainer.class);
1
GreenGiant