[Resolvido] Receber Json no Vraptor 3

Estou com um problema do qual não encontrei a solução na documentação do Vraptor.

Tenho uma array de um Objeto em javascript, e gostaria de enviar essa Array, para um método na minha lógico do Vraptor3.

Este é meu método no meu Controller Vraptor.

public void fecharVenda(List<ItemVenda> itemVendas){
        
}

Gostaria de saber como devo fazer para receber essa lista no meu controller.

esse array tem objetos que correspondem a um itemVenda?

tipo:

[{id: 2, item: "abc", preco: 234.56}, ...]

vc precisa criar um object com os parâmetros da requisição que o VRaptor espera:

var dados = {
   "itemVendas[0].id" : 2,
   "itemVendas[0].item" : "abc",
   "itemVendas[0].preco" : 234.56,
   "itemVendas[1].id" : 3,
   "itemVendas[1].item" : "def",
   "itemVendas[1].preco" : 2.99,
   ....
};

e pra passar pro controller vc pode usar o jquery:

$.post("/url/do/controller", dados, function(response) {
    //faz alguma coisa com o response
});

Valeu Lucas, era isso mesmo que eu queria, funcionou blz.

Buenas! Estava com o mesmo problema! Show de bola o VRaptor!!!

Estou com problema semelhante para receber dados de uma requisição Ajax usando json…
Poderiam, por favor, colocar o código Controller q fizeram pra receber os dados?

Controller anotado com @post / @Consumes("application/json").
O jQuery/Ajax informando no envio type: "post", dataType: "json",contentType: "application/json;"

Obrigado!

Problema no JSON.stringify que não tava convertendo o objeto (só os atributos), arrumei na mão e rolou no lado do servidor, o problema tá na view mesmo :slight_smile:
abs

Agora está dando problema para enviar lista do Json (via Ajax), não estou conseguindo receber array.
Estou fazendo na mão simplificando (esse dado é um list de um objeto - “carro.multas”).

No client (javascript)

 dados = '{"multas":["R$20","R$30","R$40","R$50","R$60","R$70"]}' ;

No servidor (vraptor 3)

@Consumes("application/json")
@Post 
public void receberMultas(ArrayList&lt;String&gt; multas){...}
// gera exception: br.com.caelum.vraptor.http.InvalidParameterException: Exception when trying to instantiate Target(name=multas, type=class java.util.ArrayList)

Vi alguma a opção de trabalhar com Gson, baixei mas não consigo receber nem em formato de string o parâmetro

@Consumes("application/json")  // sem @Consumes e tirando contentType: "application/json; do client nada muda
@Post 
public void receberMultas(String multas){...}
//não gera exception mas tb não recebo o string

formatando num estado bem simples (não em forma de lista), consigo receber o parâmetro…

dados = '{"multas":"R$20"}' ;

Alguma luz?
abs

não vai funcionar com uma lista… vc precisa criar um VO pra encapsular a lista:

class Multas {
   List<String> multas;
}

e receber esse cara no método. É uma limitação do deserializer de json que a gente usa no vraptor (XStream)

Entendi, o json completo é a serialização de uma classe Carro que contém Multas.

[code]public class Carro{
public String nome;
public String modelo;
public String placa;
public List<String> multas;

gets/sets
}
[/code]
Criei então uma classe de multa

public class Multa { public String valor; ... } // alterei a Classe de carro pra tratar a lista de objetos Multa agora public class Carro{ public List&lt;Multa&gt; multas; ... }
De qq forma gera uma exception acusando duplicação de campo… vou investigar mais isso, mas pelo jeito é o caminho mais certo

SEVERE: Unhandled exception occurred whilst decorating page com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$DuplicateFieldException: multas ---- Debugging information ---- duplicate-field : multas class : fiat.model.entity.Veiculo required-type : fiat.model.entity.Veiculo line number : -1 -------------------------------

O json enviado do client

Vlw
abs

creio que o formato correto seria:

{"veiculo":{"nome":"Palio","placa":"PAL - 00000","multas":[{"valor":"R$20"},{"valor": "R$30"}]}}

Usei o JSON gerado de um parser do form.

De qq forma, colocando na mão

gera a exception

tá fogo rs
abs

cara, listas no JSON são horríveis… principalmente com o XStream… o formato que ele aceita pra deserializar é diferente do formato pra serializar…

com a lista de string dentro do Carro não funcionou também? (e o formato anterior do json)

Realmente, considerando q se trata de algo padronizado, não era pra ser tão sofrido assim…
Mas resumindo os testes:

Lista tipo String:

[code]dados = ‘{“veiculo”:{“nome”:“Palio”,“placa”:“PAL - 00000”,“multas”:[“R$20”,“R$30”,“R$40”,“R$50”,“R$60”,“R$70”]}}’ ;
+
ArrayList<String> multas;

EXCEPTION
com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$DuplicateFieldException: multas
---- Debugging information ----
duplicate-field : multas
class : fiat.model.entity.Veiculo
required-type : fiat.model.entity.Veiculo
line number : -1
-------------------------------[/code]
Lista tipo objeto

[code]dados = ‘{“veiculo”:{“nome”:“Palio”,“placa”:“PAL - 00000”,“multas”:[{“valor”:“R$20”},{“valor”: “R$30”}]}}’ ;
+
ArrayList<Multa> multas; // Class Multa{ public String valor; …gets/sets… }

EXCEPTION
com.thoughtworks.xstream.converters.ConversionException: valor : valor : valor : valor
---- Debugging information ----
message : valor : valor
cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message : valor : valor
class : fiat.model.entity.Veiculo
required-type : java.util.ArrayList
line number : -1
-------------------------------[/code]
Pensei em receber formato JSON como texto (sem anotar o [color=darkred]@Consumes(“application/json”)[/color]) para o método e tentar deserializar com Gson, mas o post é barrado por causa dos caracteres especiais (um texto simples vai).

abs

troca de ArrayList pra só List

Estava assim, depois q implementei a classe concreta, mas não mudou…

vc pode desistir de mandar json e mandar form parameters mesmo… vai funcionar tranquilo com o VRaptor

algum motivo forte pra ter usado json e não form parameters?

Blz, pra resolver este problema especificamente não é necessário mesmo.
Mas estou procurando ter isso resolvido pra não precisar sair desesperado atrás da solução (qdo, por ex, precisar consumir um webservice em JSON).
Encontrei gente reclamando de desearilizar listas em XML tb, então imagina…

Comecei a ler mais sobre Xstream e Jettison (o problema pode ser o Jettison).
Ainda não achei a solução, mas estou vendo algumas pistas do q pode ser o problema,
ex: "Jettison for serialization and deserialization support with JSON. Note, that newer versions 1.3.x are no longer compatible with XStream."
http://xstream.codehaus.org/download.html

Valeu man a força ae, se conseguir alguma coisa volto com a solução.
abs

xml costuma funcionar melhor, pq tudo tem raiz… mas listas em geral costumam zoar as deserializações, mesmo…

Outra coisa q tava pensando, era a possibilidade reescrever a referência da injeção de dependência no Controller deixando o Gson como padrão no lugar do XStream (não conheço Gson, mas vi nos posts q é melhor pra deserializar).

Dá pra fazer isso no VRaptor ou algo parecido?
Será q consideram lançar uma próxima versão mudando a ferramenta de deserialização?

abs

Dá pra fazer sim, só criar uma classe que implementa Deserializer (do VRaptor), anotada com @Deserializes(“application/json”)

o vraptor já vai usar a sua classe automaticamente.

Se quiser tentar implementar e colocar no VRaptor, pull requests são muito bem vindos =)