Como retornar data com json?[RESOLVIDO]

13 respostas
vasilvei

Bom dia pessoa, estou com uma dificuldade ao retornar data do banco de dados, via json, os outros campos retornam normalmente, segue abaixo o código:

JSP:

<%@taglib uri="http://www.joda.org/joda/time/tags" prefix="joda"%>

...

 <input id="dtcadastro" class="limpar" type="text" onblur="validaDat(this)" value="<joda:format pattern="dd/MM/yyyy" value= "${pessoa.dtcadastro}"/>"
                                   onkeyup="return formataCampo(this, '00/00/0000', event)" onkeypress="return desEnterLetras(this, event);" name="pessoa.dtcadastro" size="10" maxlength="10">

...

<input id="dtnasc" class="limpar" onblur="validaDat(this)" type="text" value="<joda:format pattern="dd/MM/yyyy" value= "${pessoa.dtnasc}"/>"
                                       onkeyup="return formataCampo(this, '00/00/0000', event)" onkeypress="return desEnterLetras(this, event);" name="pessoa.dtnasc" size="10" maxlength="10">

...

function funcoesPessoa() {

         
                $.getJSON("/Coliseu/primeiroPessoa", {
                    idpessoa :  $("#idpessoa").val()
                }, function(pessoa){
                    $("#idpessoa").val(pessoa.idpessoa);
                    $("#nome").val(pessoa.nome);
                    $("#cnpjf").val(pessoa.cnpjf);
                    $("#email").val(pessoa.email);
                    $("#fantasia").val(pessoa.fantasia);
                    $("#inscest").val(pessoa.inscest);
                    $("#inscmun").val(pessoa.inscmun);
                    $("#inscrural").val(pessoa.inscrural);
                    $("#atividade").val(pessoa.atividade);
                    $("#rg").val(pessoa.rg);
                    $("#empresa").val(pessoa.empresa);
                    $("#estadocivil").val(pessoa.estadocivil);
[b]                    $("#dtnasc").val(pessoa.dtnasc);
                    $("#dtcadastro").val(pessoa.dtcadastro);[/b]
                    $("#rendafamiliar").val(pessoa.rendafamiliar);
                    $("#observacao").val(pessoa.observacao);
                    $("#telefoneconta").val(pessoa.telefoneconta);
                    $("#telefone").val(pessoa.telefone);
                    $("#fax").val(pessoa.fax);
                    $("#celular").val(pessoa.celular);
                    $("#nomepai").val(pessoa.nomepai);
                    $("#nomemae").val(pessoa.nomemae);
                    $("#nomeconjuge").val(pessoa.nomeconjuge);
                    $("#celular").val(pessoa.celular);
                    $("#nomepai").val(pessoa.nomepai);
                    $("#nomemae").val(pessoa.nomemae);
                    $("#nomeconjuge").val(pessoa.nomeconjuge);
                    if( $("#idcidade").val()!= ""){
                        $("#idcidade").val(pessoa.cidade.idcidade);
                        $("#nomecidade").val(pessoa.cidade.cidade);
                        $("#siglauf").val(pessoa.cidade.uf.siglauf);
                    }                    
                });
                
            }

A classe controller

@Restrito
    @Get
    @Path("/primeiroPessoa")
    public void primeiroPessoa() {

        try {

            Pessoa pessoa = dao.primeiroOuUltimo("asc");
            result.use(Results.json()).withoutRoot().from(pessoa).include("cidade", "cidade.uf").serialize();

        } catch (Exception e) {
            result.redirectTo(PessoaController.class).pessoaEdit();
        }
    }

A Classe dao

public Pessoa primeiroOuUltimo(String ordem) throws Exception {
        Session session = Hibernate.getSession();
        List<Pessoa> list = null;
        String hql = "from Pessoa order by idpessoa " + ordem + " limit 1";
        try {
            Query query = session.createQuery(hql);
            list = query.list();
        } catch (HibernateException hibernateException) {
            list = null;
        } finally {
            session.close();
        }

        return list.get(0);
    }

O model

@Column(name = "dtnasc")
    @Type(type = "org.joda.time.contrib.hibernate.PersistentLocalDate")
    private LocalDate dtnasc;
 
    @Column(name = "dtcadastro")
    @Type(type = "org.joda.time.contrib.hibernate.PersistentLocalDate")
    private LocalDate dtcadastro;

se eu chamar a url (http://localhost:8084/Coliseu/primeiroPessoa)
ele trás os campos normalmente somente a data que não:

{
  "idpessoa": 1001,
  "nome": "Valdemir Silveirá",
  "cnpjf": "[CPF removido]",
  "fantasia": "",
  "inscest": "",
  "inscmun": "",
  "inscrural": "",
  "atividade": "Programador",
  "rg": "9.829.844-4",
  "empresa": "Patocom",
  "estadocivil": "so",
  "rendafamiliar": "1400.00",
  "sexo": "",
  "observacao": "teste de cadastro",
  "telefoneconta": "([telefone removido]",
  "telefone": "([telefone removido]",
  "fax": "",
  "celular": "([telefone removido]",
  "email": "[email removido]",
  "nomepai": "",
  "nomemae": "Bernadete Ap. Silveira",
  "nomeconjuge": "Tania Maria Sutil"
}

13 Respostas

Lucas_Cavalcanti

qual é a classe da sua data? Date? Calendar? alguma do JodaTime?

vasilvei

JodaTime

LocalDate

import org.joda.time.LocalDate;

vasilvei

Como o postgres trás data yyyy/MM/dd, daí eu achei esse jeito com jodaTime fazer trazer a data dd/MM/yyyy, por esse motivo que eu uso

import org.joda.time.LocalDate;

Lucas_Cavalcanti

tente dar um include no campo da data:

result.use(json())......include("dtnasc", "dtcadastro").serialize()

ou simplesmente

result.use(json())......recursive().serialize();

só cuidado que o último serializa todos os objetos recursivamente, então o json pode ficar gigante, ou até dar um erro se tiver dependências circulares.

vasilvei

utilizando esse:

result.use(json())......include( "dtcadastro").serialize()  

result.use(Results.json()).withoutRoot().from(pessoa).include( "dtcadastro").serialize();

ele retorna quando eu chamo na url o seguinte:

  "dtcadastro": {
    "iLocalMillis": 1300924800000
  },

eu fiz altereção no campo javascript:

...
$("#dtcadastro").val(pessoa.dtcadastro.iLocalMillis);
...

ele joga esse valor no campo do formulário: 1300924800000;

e a forma

result.use(json())......recursive().serialize(); 

ele retorna 

{
  "transportadoraCollection": [
    false,
    {
      "@class": "pessoa"
vasilvei

eu tava fazendo um teste agora e se utilizar a classe Date no model

e colocar o include(“dtcadastro”)

a tirar a taglib do jodatime

ele retorna a data no campo, só que daí ele pega exatamente como esta no banco(yyyy-MM-dd), se tiver como fazer quando ele faz a consulta transformar de modo ISO para ABNT (dd/MM/yyyy).

também resolveria o problema, o que você, tem como fazer isso?

Lucas_Cavalcanti

vc pode criar um converter, e pode ser pro jodatime:

public class LocalDateConverter extends AbstractBasicConverter { //do XStream
    @Override
    public boolean canConvert(Class type) {
         return LocalDate.class.equals(type);
    }

    //fromString vazio
    @Override
    public String toString(Object obj) {
        LocalDate date = (LocalDate) obj;
        return //data no seu formato (DateFormatter)
    }
}

e registrar no VRaptor:

@Component
public class CustomXStreamJSONSerialization extends XStreamJSONSerialization {

     //delega o construtor

     @Override
     protected XStream getXStream() {
          XStream stream = super.getXStream();
          stream.registerConverter(new LocalDateConverter());
          return stream;
     }
}
vasilvei

criei duas classes não sei se fiz certo, porque uma esta com erro (CustomXStreamJSONSerialization), e a (LocalDateConverter), pediu para implementar os metodos abstratos,
se , talves por gentileza puder me exeplificar:

o erro da CustomXStreamJSONSerialization:

cannot find symbol
  symbol:   constructor XStreamJSONSerialization()
  location: class br.com.caelum.vraptor.serialization.xstream.XStreamJSONSerialization
package br.com.coliseu.Util;

import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.serialization.xstream.XStreamJSONSerialization;
import com.thoughtworks.xstream.XStream;

/**
 *
 * @author valde
 */
@Component
public class CustomXStreamJSONSerialization extends XStreamJSONSerialization {

     //delega o construtor

     @Override
     protected XStream getXStream() {
          XStream stream = super.getXStream();
          stream.registerConverter(new LocalDateConverter());
          return stream;
     }
}

a outra

package br.com.coliseu.Util;

import com.thoughtworks.xstream.converters.basic.AbstractBasicConverter;
import java.text.SimpleDateFormat;
import org.joda.time.LocalDate;

/**
 *
 * @author valde
 */
public class LocalDateConverter extends AbstractBasicConverter { //do XStream
    @Override
    public boolean canConvert(Class type) {
         return LocalDate.class.equals(type);
    }

    //fromString vazio
    @Override
    public String toString(Object obj) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        LocalDate date = (LocalDate) obj;
        return dateFormat.format(date);
    }

    @Override
    protected Object fromString(String string) {
        throw new UnsupportedOperationException("Not supported yet.");
    }



   


}
Lucas_Cavalcanti

o comentário “//delega o construtor” era pra vc criar o construtor :wink:

dá Ctrl+1 em cima do erro (se vc usa eclipse) e ele vai sugerir pra vc criar o construtor.

vasilvei

então cara eu voltei tudo para o jodatime

e fiz as duas classes que ficaram assim:

package br.com.coliseu.Util;


import br.com.caelum.vraptor.interceptor.TypeNameExtractor;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.serialization.ProxyInitializer;
import br.com.caelum.vraptor.serialization.xstream.XStreamJSONSerialization;
import com.thoughtworks.xstream.XStream;
import javax.servlet.http.HttpServletResponse;


/**
 *
 * @author valde
// */


@Component
public class CustomXStreamJSONSerialization extends XStreamJSONSerialization {

    public CustomXStreamJSONSerialization(HttpServletResponse response,
            TypeNameExtractor extractor, ProxyInitializer initializer) {
        super(response, extractor, initializer);
    }

    @Override
    protected XStream getXStream() {
        XStream stream = super.getXStream();
        stream.registerConverter(new LocalDateConverter());
        return stream;
    }
}
package br.com.coliseu.Util;

import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
import java.text.SimpleDateFormat;
import org.joda.time.LocalDate;

/**
 *
 * @author valde
 */
public class LocalDateConverter extends AbstractSingleValueConverter {

    @Override
    public boolean canConvert(Class type) {
        return LocalDate.class.equals(type);
    }

    //fromString vazio
    @Override
    public String toString(Object obj) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        LocalDate date = (LocalDate) obj;
        return dateFormat.format(date);

    }
    @Override
    public Object fromString(String string) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

e fiz o teste debugando,

ele faz a busca retorna do banco a data yyyy/MM/dd como o esperado e passa para a classe LocalDateConverter,

daí ele passa sem dar o exception mas quando vai fazer isso

@Restrito
    @Get
    @Path("/proximoPessoa")
    public void proximoPessoa(Integer idpessoa) {
        Pessoa pessoa = null;
        try {
            pessoa = dao.proximo(idpessoa);
            result.use(Results.json()).withoutRoot().from(pessoa).include("cidade", "cidade.uf", "dtcadastro").serialize();

        } catch (Exception exception) {
            result.redirectTo(PessoaController.class).pessoaEdit();
        } 


    }

daí dá o excepetion seguinte:

"Could not get field class java.lang.reflect.Field.dtcadastro : Cannot format given Object as a Date"
vasilvei

na verdade eu tava fazendo uns teste aqui e coloquei um tray catch e vi que ele dá erro nessa parte aqui:

@Override
    public String toString(Object obj) {
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
            LocalDate date = (LocalDate) obj;
            return dateFormat.format(date);
        } catch (Exception e) {
            return "eroo";
        }

    }

na hora de converter, porque ele retorna a string (“eroo”);

Lucas_Cavalcanti

SimpleDateFormat é só pra Date mesmo… vc tem que usar o formatador do Jodatime:

return DateTimeFormat.forPattern("dd/MM/yyyy").print((LocalDate) obj)
vasilvei

Cara era isso mesmo, muito Obrigado mais uma vez!

Criado 25 de março de 2011
Ultima resposta 25 de mar. de 2011
Respostas 13
Participantes 2