[Resolvido] Receber Json no Vraptor 3

20 respostas
mascjunior

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.

20 Respostas

Lucas_Cavalcanti

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
});
mascjunior

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

donny

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

pgnt

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!

pgnt

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

pgnt

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

Lucas_Cavalcanti

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)

pgnt
Entendi, o json completo é a serialização de uma classe Carro que contém Multas.
public class Carro{
	public String nome;
	public String modelo;
	public String placa;
	public List&lt;String&gt; multas;
	
gets/sets
}
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
{"veiculo":{"nome":"Palio","placa":"PAL - 00000","multas":["R$20","R$30","R$40","R$50","R$60","R$70"]}}

Vlw
abs

Lucas_Cavalcanti

creio que o formato correto seria:

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

Usei o JSON gerado de um parser do form.

De qq forma, colocando na mão

gera a exception

tá fogo rs
abs

Lucas_Cavalcanti

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)

pgnt

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

Lista tipo String:
dados = '{"veiculo":{"nome":"Palio","placa":"PAL - 00000","multas":["R$20","R$30","R$40","R$50","R$60","R$70"]}}' ;
+
ArrayList&lt;String&gt; 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
-------------------------------
Lista tipo objeto
dados = '{"veiculo":{"nome":"Palio","placa":"PAL - 00000","multas":[{"valor":"R$20"},{"valor": "R$30"}]}}'  ;
+
ArrayList&lt;Multa&gt; 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
-------------------------------
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

Lucas_Cavalcanti

troca de ArrayList pra só List

pgnt

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

Lucas_Cavalcanti

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?

pgnt

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

Lucas_Cavalcanti

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

pgnt

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

Lucas_Cavalcanti

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 =)

pgnt

Blz, vou ver as opções qdo tiver tempo, valeu a força!!!
abs

Criado 24 de março de 2011
Ultima resposta 13 de dez. de 2012
Respostas 20
Participantes 4