Question

J'utilise Spring MVC pour gérer les requêtes POST JSON. Sous les couvertures J'utilise le MappingJacksonHttpMessageConverter construit sur le processeur Jackson JSON et activé lorsque vous utilisez le mvc: conduit annotation

.

L'un de mes services reçoit une liste d'actions:

@RequestMapping(value="/executeActions", method=RequestMethod.POST)
    public @ResponseBody String executeActions(@RequestBody List<ActionImpl> actions) {
        logger.info("executeActions");
        return "ACK";
    }

J'ai trouvé que Jackson cartes à l'requestBody une liste des éléments java.util.LinkedHashMap (liaison de données simple). Au lieu de cela, je voudrais que la demande soit liée à une liste d'objets typés (dans ce cas « ActionImpl »).

Je sais que cela est facile à faire si vous utilisez directement ObjectMapper Jackson:

List<ActionImpl> result = mapper.readValue(src, new TypeReference<List<ActionImpl>>() { }); 

mais je me demandais quelle est la meilleure façon d'y parvenir lors de l'utilisation Spring MVC et MappingJacksonHttpMessageConverter. Tous les conseils?

Merci

Était-ce utile?

La solution

problème suspect est dû au type effacement, à savoir au lieu de passer le type de paramètre générique, est peut-être passé seulement actions.getClass (); et cela donnerait type équivalent de la liste .

Si cela est vrai, une possibilité serait d'utiliser une sous-classe intermédiaire, comme:

public class ActionImplList extends ArrayList<ActionImpl> { }

parce que cela les informations de type conserver même si seule classe est passée. Alors:

public @ResponseBody String executeActions(@RequestBody ActionImplList actions)

ferait l'affaire. Pas optimale mais devrait fonctionner.

J'espère que quelqu'un avec plus de connaissances Spring MVC peut faire la lumière sur la raison pour laquelle le type de paramètre n'est pas passé (peut-être est un bug?), Mais au moins il y a un travail autour.

Autres conseils

J'ai trouvé que vous pouvez contourner le problème d'effacement de type en utilisant un tableau comme @RequestBody au lieu d'une collection. Par exemple, ce qui suit fonctionnerait:

public @ResponseBody String executeActions(@RequestBody ActionImpl[] actions) { //... }

Pour votre information, la fonction sera disponible au printemps 3.2 (voir https://jira.springsource.org/browse / SPR-9570 )

Je viens de tester sur courant M2 et il fonctionne comme un charme hors de la boîte (pas besoin de fournir une annotation additionnelle pour fournir le type paramétrées, il sera résolu automatiquement par le nouveau MessageConverter)

Cette question est déjà vieux, mais je pense que je peux apporter un peu quand même.

Comme StaxMan a souligné, cela est dû à l'effacement de type. Il a certainement devrait possible, parce que vous peut obtenir les arguments génériques par réflexion de la définition de la méthode. Cependant, le problème est l'API de HttpMessageConverter :

T read(Class<? extends T> clazz, HttpInputMessage inputMessage);

Ici, seule List.class sera transmis à la méthode. Donc, comme vous pouvez le voir, il est impossible de mettre en œuvre un HttpMessageConverter qui calcule le type réel en regardant le type de paramètre de méthode, car ce n'est pas disponible.

Néanmoins, il est possible de coder votre propre solution de contournement - vous ne pourrez pas utiliser HttpMessageConverter. Spring MVC vous permet d'écrire votre propre WebArgumentResolver qui se déclenche avant que les méthodes de résolution standard. Vous pouvez par exemple utiliser votre propre annotation personnalisée (@JsonRequestBody?) Qui utilise directement un ObjectMapper pour analyser votre valeur. Vous serez en mesure de fournir le type de paramètre de la méthode:

final Type parameterType= method.getParameterTypes()[index];
List<ActionImpl> result = mapper.readValue(src, new TypeReference<Object>>() {
    @Override
    public Type getType() {
        return parameterType;
    }
});

Pas vraiment la façon dont typereference était destiné à être utilisé, je présume, mais ObjectMapper ne fournit pas une méthode plus appropriée.

Avez-vous essayé de déclarer la méthode comme:

executeActions(@RequestBody TypeReference<List<ActionImpl>> actions)

Je n'ai pas essayé, mais en fonction de votre question, il est la première chose que je serait essayer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top