web-dev-qa-db-fra.com

recevoir json et désérialiser sous forme de liste d'objets au contrôleur mvc de ressort

Mon code est comme ci-dessous:

manette

@RequestMapping(value="/setTest", method=RequestMethod.POST, consumes="application/json")
public @ResponseBody ModelMap setTest(@RequestBody List<TestS> refunds, ModelMap map) {
    for(TestS r : refunds) {
        System.out.println(r.getName());
    }
    // other codes
}

TestS pojo

public class TestS implements Serializable {
    private String name;
    private String age;
    //getter setter
}

Demande Json

var z = '[{"name":"1","age":"2"},{"name":"1","age":"3"}]';
$.ajax({
    url: "/setTest",
    data: z,
    type: "POST",
    dataType:"json",
    contentType:'application/json'               
});

Ça donne cette erreur 

Exception Java.lang.ClassCast: Java.util.LinkedHashMap ne peut pas être converti en com.gogoair.cidb.entities.TestS

J'utilise spring 3.1.2 et jackson 2.0.4

Edit: Je souhaite recevoir la liste des objets TestS à la méthode de mon contrôleur et les traiter. Je ne parviens pas à déterminer si j'envoie une erreur JSON ou si la signature de ma méthode est fausse.

26
HKumar

Voici le code qui fonctionne pour moi. La clé est que vous avez besoin d'une classe wrapper.

public class Person {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

Une classe PersonWrapper

public class PersonWrapper {

    private List<Person> persons;

    /**
     * @return the persons
     */
    public List<Person> getPersons() {
        return persons;
    }

    /**
     * @param persons the persons to set
     */
    public void setPersons(List<Person> persons) {
        this.persons = persons;
    }
}

Mes méthodes de contrôleur

@RequestMapping(value="person", method=RequestMethod.POST,consumes="application/json",produces="application/json")
    @ResponseBody
    public List<String> savePerson(@RequestBody PersonWrapper wrapper) {
        List<String> response = new ArrayList<String>();
        for (Person person: wrapper.getPersons()){
        personService.save(person);
         response.add("Saved person: " + person.toString());
    }
        return response;
    }

La demande envoyée est json dans POST 

{"persons":[{"name":"shail1","age":"2"},{"name":"shail2","age":"3"}]}

Et la réponse est 

["Saved person: Person [name=shail1, age=2]","Saved person: Person [name=shail2, age=3]"]
39
Shailendra

Ce n'est pas possible de la façon dont vous l'essayez. Le débrouillage de Jackson fonctionne sur le code Java compilé after type erasure. Donc votre

public @ResponseBody ModelMap setTest(@RequestBody List<TestS> refunds, ModelMap map) 

est vraiment seulement

public @ResponseBody ModelMap setTest(@RequestBody List refunds, ModelMap map) 

(pas de génériques dans la liste arg).

Le type par défaut créé par Jackson lors de l'annulation d'une List est une LinkedHashMap.

Comme mentionné par @Saint, vous pouvez contourner ce problème en créant votre propre type pour la liste, comme suit:

class TestSList extends ArrayList<TestS> { }

puis en modifiant votre signature de contrôleur pour 

public @ResponseBody ModelMap setTest(@RequestBody TestSList refunds, ModelMap map) {
11
Dirk Lachowski
@RequestMapping(
         value="person", 
         method=RequestMethod.POST,
         consumes="application/json",
         produces="application/json")
@ResponseBody
public List<String> savePerson(@RequestBody Person[] personArray) {
    List<String> response = new ArrayList<String>();
    for (Person person: personArray) {
        personService.save(person);
        response.add("Saved person: " + person.toString());
    }
    return response;
}

Nous pouvons utiliser Array comme indiqué ci-dessus.

7
Deepak

La solution fonctionne très bien, 

public List<String> savePerson(@RequestBody Person[] personArray)  

Pour cette signature, vous pouvez passer le tableau Person de postman comme 

[
{
  "empId": "10001",
  "tier": "Single",
  "someting": 6,
  "anything": 0,
  "frequency": "Quaterly"
}, {
  "empId": "10001",
  "tier": "Single",
  "someting": 6,
  "anything": 0,
  "frequency": "Quaterly"
}
]

N'oubliez pas d'ajouter la balise consumes:

@RequestMapping(value = "/getEmployeeList", method = RequestMethod.POST, consumes="application/json", produces = "application/json")
public List<Employee> getEmployeeDataList(@RequestBody Employee[] employeearray) { ... }
0
AmitG

Pour moi, le code ci-dessous a fonctionné, en envoyant d'abord la chaîne json avec les en-têtes appropriés

$.ajax({
        type: "POST",
        url : 'save',
        data : JSON.stringify(valObject),
        contentType:"application/json; charset=utf-8",
        dataType:"json",
        success : function(resp){
            console.log(resp);
        },
        error : function(resp){
            console.log(resp);
        }
    });

Et puis côté printemps -

@RequestMapping(value = "/save", 
                method = RequestMethod.POST,
                consumes="application/json")
public @ResponseBody String  save(@RequestBody ArrayList<KeyValue> keyValList) {
    //Saving call goes here
    return "";
}

Ici, KeyValue est un simple pojo qui correspond à votre structure JSON. Vous pouvez également ajouter des produits à votre guise.

Mon objet json est comme ça -

[{"storedKey":"vc","storedValue":"1","clientId":"1","locationId":"1"},
 {"storedKey":"vr","storedValue":"","clientId":"1","locationId":"1"}]
0
Pratik Goenka