web-dev-qa-db-fra.com

Paramètre JSON dans le contrôleur MVC à ressort

J'ai

@RequestMapping(method = RequestMethod.GET)
@ResponseBody
SessionInfo register(UserProfile profileJson){
  ...
}

Je passe profilJson de cette façon:

http://server/url?profileJson={"email": "[email protected]"}

mais mon objet profileJson a tous les champs nuls. Que dois-je faire pour que Spring analyse mon json?

27
Stepan Yakovenko

Cela pourrait être fait avec un éditeur personnalisé, qui convertit le JSON en objet UserProfile:

public class UserProfileEditor extends PropertyEditorSupport  {

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        ObjectMapper mapper = new ObjectMapper();

        UserProfile value = null;

        try {
            value = new UserProfile();
            JsonNode root = mapper.readTree(text);
            value.setEmail(root.path("email").asText());
        } catch (IOException e) {
            // handle error
        }

        setValue(value);
    }
}

C'est pour enregistrer l'éditeur dans la classe de contrôleur:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(UserProfile.class, new UserProfileEditor());
}

Et voici comment utiliser l'éditeur, pour annuler le paramètre JSONP:

@RequestMapping(value = "/jsonp", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
SessionInfo register(@RequestParam("profileJson") UserProfile profileJson){
  ...
}
25
Angular University

La solution à ce problème est si facile et si simple qu’elle vous fera presque rire, mais avant même d’y arriver, permettez-moi d’abord de souligner qu’aucun développeur Java qui se respecte ne se respecte, et je veux dire JAMAIS travailler avec JSON sans utilisant la bibliothèque JSON hautes performances de Jackson.

Jackson n’est pas seulement un cheval de travail et une bibliothèque JACT de facto pour les développeurs Java, il fournit également toute une série d’appels d’API rendant l’intégration JSON avec Java un jeu d'enfant (vous pouvez télécharger Jackson à http://jackson.codehaus.org/ ).

Maintenant pour la réponse. En supposant que vous avez un pojo UserProfile qui ressemble à ceci:

public class UserProfile {

private String email;
// etc...

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

// more getters and setters...
}

... alors votre méthode Spring MVC pour convertir un nom de paramètre GET "profileJson" avec la valeur JSON de {"email": "[email protected]"} ressemblerait à ceci dans votre contrôleur:

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper; // this is your lifesaver right here

//.. your controller class, blah blah blah

@RequestMapping(value="/register", method = RequestMethod.GET) 
public SessionInfo register(@RequestParam("profileJson") String profileJson) 
throws JsonMappingException, JsonParseException, IOException {

    // now simply convert your JSON string into your UserProfile POJO 
    // using Jackson's ObjectMapper.readValue() method, whose first 
    // parameter your JSON parameter as String, and the second 
    // parameter is the POJO class.

    UserProfile profile = 
            new ObjectMapper().readValue(profileJson, UserProfile.class);

        System.out.println(profile.getEmail());

        // rest of your code goes here.
}

Bam! Vous avez terminé. Je vous encouragerais à parcourir l'essentiel de l'API Jackson, car, comme je l'ai dit, cela sauve des vies. Par exemple, retournez-vous du JSON depuis votre contrôleur? Si c'est le cas, tout ce que vous avez à faire est d'inclure JSON dans votre bibliothèque et de retourner votre POJO. Jackson le convertira AUTOMATIQUEMENT en JSON. Vous ne pouvez pas obtenir beaucoup plus facile que cela. À votre santé! :-)

30
The Saint

Vous pouvez créer votre propre Converter et laisser Spring l’utiliser automatiquement le cas échéant:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
class JsonToUserProfileConverter implements Converter<String, UserProfile> {

    private final ObjectMapper jsonMapper = new ObjectMapper();

    public UserProfile convert(String source) {
        return jsonMapper.readValue(source, UserProfile.class);
    }
}

Comme vous pouvez le voir dans la méthode de contrôleur suivante, rien de spécial n'est nécessaire:

@GetMapping
@ResponseBody
public SessionInfo register(@RequestParam UserProfile userProfile)  {
  ...
}

Spring sélectionne automatiquement le convertisseur si vous utilisez le balayage de composants et annotez la classe de convertisseur avec @Component.

En savoir plus sur Spring Converter et conversions de types dans Spring MVC .

3
deamon

Cela résout mon problème immédiat, mais je suis toujours curieux de savoir comment vous pouvez passer dans plusieurs objets JSON via un appel AJAX.

La meilleure façon de procéder consiste à avoir un objet wrapper contenant les deux (ou plusieurs) objets à transmettre. Vous construisez ensuite votre objet JSON en tant que tableau des deux objets, c.-à-d.

[
  {
    "name" : "object1",
    "prop1" : "foo",
    "prop2" : "bar"
  },
  {
    "name" : "object2",
    "prop1" : "hello",
    "prop2" : "world"
  }
]

Ensuite, dans votre méthode de contrôleur, vous recevez le corps de la demande en tant qu’objet unique et extrayez les deux objets contenus. c'est à dire:

@RequestMapping(value="/handlePost", method = RequestMethod.POST, consumes = {      "application/json" })
public void doPost(@RequestBody WrapperObject wrapperObj) { 
     Object obj1 = wrapperObj.getObj1;
     Object obj2 = wrapperObj.getObj2;

     //Do what you want with the objects...


}

L'objet wrapper ressemblerait à quelque chose comme ...

public class WrapperObject {    
private Object obj1;
private Object obj2;

public Object getObj1() {
    return obj1;
}
public void setObj1(Object obj1) {
    this.obj1 = obj1;
}
public Object getObj2() {
    return obj2;
}
public void setObj2(Object obj2) {
    this.obj2 = obj2;
}   

}
1
Zigri2612