Usando o XStream para serializar e desserializar objetos Java para XML
O XStream é uma biblioteca simples e poderosa que facilita muito nossa vida quando precisamos serializar objetos Java para arquivos XML e também para fazer o processo inverso. A partir de JavaBeans podemos escrever os XML com poucas linhas de código.
Nesse artigo o uso básico e o intermediário do XStream. Veremos como serializar e desserializar objetos, o uso de aliases e list.
O ambiente que usei para criar esse artigo foi o seguinte:
- Windows XP – SP3
- JDK 6
- Eclipse 3.4 – Ganymede
- XStream 1.3.1
Para começar, precisamos baixar a biblioteca para ser usada. Acessem o site oficial do XStream (http://xstream.codehaus.org), cliquem em “Download” e baixem a última versão da versão binária (Binary Distribution).
Depois de baixado, descompacte o arquivo e você verá diversos arquivos JARs. Não precisamos de todos, porém se quiser pode adicionar todos no classpath do seu projeto ou aqueles que mais se encaixarem em suas necessidades. No site do XStream tem uma explicação sobre cada uma das dependências opcionais. Acesse: http://xstream.codehaus.org/download.html.
Depois de adicionar os JARs no classpath, estamos prontos para começar a codificar. Nosso primeiro exemplo será serializar um objeto simples (JavaBean) para XML. Vamos criar esse objeto:
package com.meupost.beans; public class Agenda { private String nomePessoa; private int idade; private String email; private String telefone; private String fax; public String getNomePessoa() { return nomePessoa; } public void setNomePessoa(String nomePessoa) { this.nomePessoa = nomePessoa; } public int getIdade() { return idade; } public void setIdade(int idade) { this.idade = idade; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTelefone() { return telefone; } public void setTelefone(String telefone) { this.telefone = telefone; } public String getFax() { return fax; } public void setFax(String fax) { this.fax = fax; } }
Beleza! O objeto é esse. Vamos mandar ele para um XML. No nosso exemplo faço a serialização direto no void main(). Vejam:
package com.meupost.main; import com.meupost.beans.Agenda; import com.thoughtworks.xstream.XStream; public class Main { public static void main(String args[]) { Agenda a1 = new Agenda(); a1.setEmail("amigo1@email.com.br"); a1.setFax("123-4567"); a1.setIdade(55); a1.setNomePessoa("Fernando Pessoa"); a1.setTelefone("654-3210"); XStream x = new XStream(); System.out.println(x.toXML(a1)); } }
A saída será assim:
<com.meupost.beans.Agenda> <nomePessoa>Fernando Pessoa</nomePessoa> <idade>55</idade> <email>amigo1@email.com.br</email> <telefone>654-3210</telefone> <fax>123-4567</fax> </com.meupost.beans.Agenda>
Muito bom. Mas agora vamos complicar mais um pouco. Vamos criar mais um objeto chamado Endereco que vai conter onde nosso indivíduo mora. Esse objeto Endereco entrará como atributo do objeto Agenda. Vejam o exemplo abaixo de como fica e o resultado do XML.
Objeto Endereco:
package com.meupost.beans; public class Endereco { private String rua; private int numero; private String cidade; private String estado; public String getRua() { return rua; } public void setRua(String rua) { this.rua = rua; } public int getNumero() { return numero; } public void setNumero(int numero) { this.numero = numero; } public String getCidade() { return cidade; } public void setCidade(String cidade) { this.cidade = cidade; } public String getEstado() { return estado; } public void setEstado(String estado) { this.estado = estado; } }
Objeto Agenda. Reparem que adicionamos o atributo Endereco!
package com.meupost.beans; public class Agenda { private String nomePessoa; private int idade; private String email; private String telefone; private String fax; private Endereco endereco; public String getNomePessoa() { return nomePessoa; } public void setNomePessoa(String nomePessoa) { this.nomePessoa = nomePessoa; } public int getIdade() { return idade; } public void setIdade(int idade) { this.idade = idade; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTelefone() { return telefone; } public void setTelefone(String telefone) { this.telefone = telefone; } public String getFax() { return fax; } public void setFax(String fax) { this.fax = fax; } public Endereco getEndereco() { return endereco; } public void setEndereco(Endereco endereco) { this.endereco = endereco; } }
E agora o teste e resultado:
package com.meupost.main; import com.meupost.beans.Agenda; import com.meupost.beans.Endereco; import com.thoughtworks.xstream.XStream; public class Main { public static void main(String args[]) { Agenda a1 = new Agenda(); a1.setEmail("amigo1@email.com.br"); a1.setFax("123-4567"); a1.setIdade(55); a1.setNomePessoa("Fernando Pessoa"); a1.setTelefone("654-3210"); Endereco end = new Endereco(); end.setRua("Rua Saldanha Marinho"); end.setNumero(1234); end.setCidade("São José do Rio Preto"); end.setEstado("São Paulo"); a1.setEndereco(end); XStream x = new XStream(); System.out.println(x.toXML(a1)); } }
Ótimo. E por fim o XML gerado:
<com.meupost.beans.Agenda> <nomePessoa>Fernando Pessoa</nomePessoa> <idade>55</idade> <email>amigo1@email.com.br</email> <telefone>654-3210</telefone> <fax>123-4567</fax> <endereco> <rua>Rua Saldanha Marinho</rua> <numero>1234</numero> <cidade>São José do Rio Preto</cidade> <estado>São Paulo</estado> </endereco> </com.meupost.beans.Agenda>
Viram que dentro do nó endereco temos os atributos que definimos no nosso objeto? Pois bem, é assim que você pode relacionar os JavaBeans.
Vocês já devem ter percebido que o nome do nó raiz ta o mesmo nome do pacote. Isso com certeza é um incoveniente muito grande quando colocamos nosso sistema em produção. Para arrumarmos isso, podemos usar os Aliases que o XStream oferece. Basta uma linha de código. Vamos mudar nosso método void main() adicionando o alias e vamos gerar o XML novamente. Vejam:
package com.meupost.main; import com.meupost.beans.Agenda; import com.meupost.beans.Endereco; import com.thoughtworks.xstream.XStream; public class Main { public static void main(String args[]) { Agenda a1 = new Agenda(); a1.setEmail("amigo1@email.com.br"); a1.setFax("123-4567"); a1.setIdade(55); a1.setNomePessoa("Fernando Pessoa"); a1.setTelefone("654-3210"); Endereco end = new Endereco(); end.setRua("Rua Saldanha Marinho"); end.setNumero(1234); end.setCidade("São José do Rio Preto"); end.setEstado("São Paulo"); a1.setEndereco(end); XStream x = new XStream(); //Adicionei nova linha aqui! x.alias("agenda", Agenda.class); System.out.println(x.toXML(a1)); } }
E o resultado:
<agenda> <nomePessoa>Fernando Pessoa</nomePessoa> <idade>55</idade> <email>amigo1@email.com.br</email> <telefone>654-3210</telefone> <fax>123-4567</fax> <endereco> <rua>Rua Saldanha Marinho</rua> <numero>1234</numero> <cidade>São José do Rio Preto</cidade> <estado>São Paulo</estado> </endereco> </agenda>
Agora, vamos fazer o processo inverso. Ao invés de escrevermos o XML, vamos ler e criar os objeto a partir do XML. Para facilitar, vamos usar nossos objetos já criados (Agenda e Endereco). Abaixo há um exemplo onde crio um objeto String com o XML a ser lido, passo a String ao XStream e o próprio se encarrega de criar nossos objetos JavaBean de volta sem esforço nenhum.
package com.meupost.main; import com.meupost.beans.Agenda; import com.meupost.beans.Endereco; import com.thoughtworks.xstream.XStream; public class Main { public static void main(String args[]) { String xml; xml = "<agenda>" + "<nomePessoa>Angelina Jolie</nomePessoa>" + "<idade>35</idade>" + "<email>angelina@jolie.com</email>" + "<telefone>1742-5236</telefone>" + "<fax>6541-222</fax>" + "<endereco>" + ="<rua>Rubião Júnior</rua>" + "<numero>2104</numero>" + "<cidade>São José do Rio Preto</cidade>" + "<estado>São Paulo</estado>" + "</endereco>" + "</agenda>"; XStream x = new XStream(); x.alias("agenda", Agenda.class); Agenda a = (Agenda) x.fromXML(xml); System.out.println(a.getNomePessoa()); } }
Vejam que no exemplo acima eu precisei indicar qual a classe que o nó raiz “agenda” fazia parte. Depois foi só passar o XML para o XStream e fazer o Cast para obter o objeto. Por fim exibimos em console o nome da Angelina!
Agora mais um problema tanto para leitura quanto para escrita do XML. E quando temos várias informações dentro de um nó? Por exemplo, temos um XML precido com esse abaixo:
<agenda> <pessoas> <pessoa> <nomePessoa>Fernando Pessoa</nomePessoa> <idade>55</idade> <email>amigo1@email.com.br</email> <telefone>124-6984</telefone> <fax>654-3210</fax> <endereco> <rua>Rua Saldanha Marinho</rua> <numero>5110</numero> <cidade>São José do Rio Preto</cidade> <estado>São Paulo</estado> </endereco> </pessoa> <pessoa> <nomePessoa>felipao@email.com.br</nomePessoa> <idade>60</idade> <email>amigo1@email.com.br</email> <telefone>2310-1110</telefone> <fax>211-4100</fax> <endereco> <rua>Rua Francisco Glicério</rua> <numero>210</numero> <cidade>Campinas</cidade> <estado>São Paulo</estado> </endereco> </pessoa> <pessoa> <nomePessoa>Raul Seixas</nomePessoa> <idade>78</idade> <email>raulzito@email.com.br</email> <telefone>222-2222</telefone> <fax>111-1111</fax> <endereco> <rua>Rua Mar Vermelho</rua> <numero>450</numero> <cidade>Babilônia</cidade> <estado>São Paulo</estado> </endereco> </pessoa> </pessoas> </agenda>
Temos vários nós pessoa. Como se fosse uma lista de pessoas. E para tratarmos isso com o XStream? Temo como? Sim, lógico que tem. Primeiramente vamos criar o objeto (JavaBean) Pessoa contendo os mesmos atributos que havia no objeto Agenda, pois agora o objeto Agenda vai conter somente um atributo que é a lista de pessoas. Veja como fica o objeto Agenda e o objeto Pessoa:
Agenda:
package com.meupost.beans; import java.util.ArrayList; import java.util.List; public class Agenda { private List<Pessoa> pessoas = new ArrayList<Pessoa>(); public void add(Pessoa pessoa) { this.pessoas.add(pessoa); } public List<Pessoa> getContent() { return this.pessoas; } }
Pessoa:
package com.meupost.beans; public class Pessoa { private String nomePessoa; private int idade; private String email; private String telefone; private String fax; private Endereco endereco; public String getNomePessoa() { return nomePessoa; } public void setNomePessoa(String nomePessoa) { this.nomePessoa = nomePessoa; } public int getIdade() { return idade; } public void setIdade(int idade) { this.idade = idade; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTelefone() { return telefone; } public void setTelefone(String telefone) { this.telefone = telefone; } public String getFax() { return fax; } public void setFax(String fax) { this.fax = fax; } public Endereco getEndereco() { return endereco; } public void setEndereco(Endereco endereco) { this.endereco = endereco; } }
Viram a diferença? Agora o objeto agenda possui uma List onde podemos ir adicionando o objeto Pessoa. O XStream ficará responsável de ler essa List e colocar no XML. Abaixo veja o exemplo de preenchimento dos objetos e o resultado depois que o XStream transforma para XML:
package com.meupost.main; import com.meupost.beans.Agenda; import com.meupost.beans.Endereco; import com.meupost.beans.Pessoa; import com.thoughtworks.xstream.XStream; public class Main { public static void main(String args[]) { Agenda a1 = new Agenda(); Pessoa p1 = new Pessoa(); p1.setEmail("amigo1@email.com.br"); p1.setFax("654-3210"); p1.setIdade(55); p1.setNomePessoa("Fernando Pesso"); p1.setTelefone("124-6984"); Endereco e1 = new Endereco(); e1.setRua("Rua Saldanha Marinho"); e1.setCidade("São José do Rio Preto"); e1.setNumero(5110); e1.setEstado("São Paulo"); p1.setEndereco(e1); Pessoa p2 = new Pessoa(); p2.setEmail("amigo1@email.com.br"); p2.setFax("211-4100"); p2.setIdade(60); p2.setNomePessoa("felipao@email.com.br"); p2.setTelefone("2310-1110"); Endereco e2 = new Endereco(); e2.setRua("Rua Francisco Glicério"); e2.setCidade("Campinas"); e2.setNumero(210); e2.setEstado("São Paulo"); p2.setEndereco(e2); Pessoa p3 = new Pessoa(); p3.setEmail("raulzito@email.com.br"); p3.setFax("111-1111"); p3.setIdade(78); p3.setNomePessoa("Raul Seixas"); p3.setTelefone("222-2222"); Endereco e3 = new Endereco(); e3.setRua("Rua Mar Vermelho"); e3.setCidade("Babilônia"); e3.setNumero(450); e3.setEstado("São Paulo"); p3.setEndereco(e3); a1.add(p1); a1.add(p2); a1.add(p3); XStream x = new XStream(); x.alias("agenda", Agenda.class); x.alias("pessoa", Pessoa.class); String xml = x.toXML(a1); System.out.println(xml); } }
E a nossa saída em XML:
<agenda> <pessoas> <pessoa> <nomePessoa>Fernando Pesso</nomePessoa> <idade>55</idade> <email>amigo1@email.com.br</email> <telefone>124-6984</telefone> <fax>654-3210</fax> <endereco> <rua>Rua Saldanha Marinho</rua> <numero>5110</numero> <cidade>São José do Rio Preto</cidade> <estado>São Paulo</estado> </endereco> </pessoa> <pessoa> <nomePessoa>felipao@email.com.br</nomePessoa> <idade>60</idade> <email>amigo1@email.com.br</email> <telefone>2310-1110</telefone> <fax>211-4100</fax> <endereco> <rua>Rua Francisco Glicério</rua> <numero>210</numero> <cidade>Campinas</cidade> <estado>São Paulo</estado> </endereco> </pessoa> <pessoa> <nomePessoa>Raul Seixas</nomePessoa> <idade>78</idade> <email>raulzito@email.com.br</email> <telefone>222-2222</telefone> <fax>111-1111</fax> <endereco> <rua>Rua Mar Vermelho</rua> <numero>450</numero> <cidade>Babilônia</cidade> <estado>São Paulo</estado> </endereco> </pessoa> </pessoas> </agenda>
Bem, estamos chegando quase no fim do artigo. Mostrei como usar o XStream para escrever XML e como ler. Ainda há muito o que aprender sobre o XStream como os aliases de campo (aliasField) e atributos. Mas esse artigo não irá se aprofundar tanto. Espero que com o que foi mostrado e ensinado aqui seja o suficiente para um início. Há um pouco de material de estudo no site do XStream, mas também é básico. O melhor mesmo é ir no Google ou mexer no JavaDoc do XStream (http://xstream.codehaus.org/javadoc/index.html).
Para praticar você pode usar diversas APIs disponíveis como o do YouTube, Mercado Livre, Yahoo… Esses XMLs são mais complexos e são ótimos para estudo.
Até a próxima!




há 11 meses atrás
Parabéns pelo Blog
Estou fazendo um trabalho onde tenho que cadastrar pessoas desde que não existam ainda.
Tenho que usar Stream e xml.
Tem uma dica pra me dar ?
Obrigado
há 10 meses atrás
cara muito bm esse totorial,
voce sobre xml e com outros tipos de arquivo!
há 8 meses atrás
Muito bem escrito. Uma liguagem muito clara e simples sem codigos avançados. Dai e só usar a cabeça para os demais problemas da atividade.
há 7 meses atrás
Parabéns pelo tutorial!
há 6 meses atrás
Ola muito boa sua explicacao….
eu estou com uma duvida gostaria de uma ajuda…
eu tenho o meu xml exemplo:
valor1
valor2
como esta ai.
eu preciso abrir ele (carregar o arquivo) e adicionar mais nos. exeplo:
valor1
valor2
valor1
valor2
teria como??? procurei no google por tudo nao achei nada :(
Obrigado…
Att. Mario..
favor responder no meu e-mail ou aki mesmo :)
há 6 meses atrás
Tentei fazer o tutorial seguindo o mesmo ambiente deste artigo, mas não consegui gerar o produto no eclipse, apesar de compilar sem problemas.
O que fiz foi pegar o xstream-1.3.1.jar e o copiei para uma pasta “lib” dentro do meu projeto. No eclipse, dentro da pasta lib, selecionei o .jar e fiz um “Build Path”|”Add to Build Path”. A compilação não apresenta nenhum erro, mas quando gero o produto obtenho a seguinte mensagem: “Could not create the view: com/thoughtworks/xstream/XStream”. Nos detalhes aparece o seguinte: “java.lang.ClassNotFoundException: com.thoughtworks.xstream.XStream”.
Eu entendi que o produto não está achando o jar, mas como faço isso?
Desde já agradeço,
Flávio
há 6 meses atrás
@Flávio
Apesar de não ter se passado muito tempo entre o meu post e a resposta, estive tentando resolvê-la há muito tempo antes disto.
A solução foi ir na aba de “Runtime” do meu projeto, e no “Classpath” adicionar o .jar que estava no meu diretório lib.
[]s,
Flávio