Java – Serializar a XML con XStream

febrero 17, 2009

Hace poco comparaba la serializacion en .NET con la de Java. En ese entonces utilice una libreria llamada Simple. Ahora me he encontrado con otra libreria llamada XStream que me ha gustado bastante.
Un problema que tuve, fue para serializar una clase que tenia atributos derivados(calculated,transient).
Tomemos el ejemplo del tutorial de XStream y modifiquemoslo

public class Person {
  private String firstname;
  private String lastname;

  public String getFullname(){
    return this.firstname+this.lastname;
  }
  public void setFullname(){
    throw new IllegalArgumentException(“Atributo de solo lectura”);
  }
  // … constructors and methods
}

luego lo serializamos de la siguiente forma

Person joe = new Person(“Joe”, “Walnes”);
Stream xstream = new XStream();
xstream.alias(“person”, Person.class);
String xml = xstream.toXML(joe);

que nos resulta en el siguiente XML

<person>
  <firstname>Joe</firstname>
  <lastname>Walnes</lastname>
</person>

notese que no aparece por ningun lado nuestro atributo calculado “Fullname”
Esto se debe a que la libreria XStream utiliza la reflexión para serializar nuestra clase y por ello accesa directamente a los campos de nuestra clase. Y no tenemos ningun campo que se llame fullname.
La solución podría ser agregar un campo llamado fullname y actualizarlo cada que se modifique alguno de los campos de los cuales depende ‘:-) uffff
Otra opción es utilizar la clase JavaBeanConverter para indicarle a XStream que debe utilizar los getters y setters de nuestra clase para serializar. Para ello necesitamos que nuestra clase cumpla la definicion de un JavaBean(constructor por default, getters y setters basicamente). Es por esto que en la clase de ejemplo tambien codificamos un método setFullname pero simplemente arrojamos una excepción si se intenta establecer algún valor.
Ahora si, veamos como utilizamos la clase JavaBeanConverter

Person joe = new Person(“Joe”, “Walnes”);
Stream xstream = new XStream();
xstream.alias(“person”, Person.class);
xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()),-20);
String xml = xstream.toXML(joe);

Nótese el segundo parámetro del método registerConverter(-20), sin éste, la serialización falla miserablemente. El valor lo obtuve de aqui, creo que ese es un fallo de XStream(la documentación)
y finalmente nos produce el XML deseado

<person>
  <fullname>Joe Walnes</fullname>
</person>

Anuncios

5 comentarios to “Java – Serializar a XML con XStream”

  1. Victor Says:

    Haz podido deserealizar un xml en un objeto que contiene un List dentro.
    Me lee bien los atributos del List pero siempre los completa con null. Siguiendo el ej :
    public class Person {
    private String firstname;
    private String lastname;
    private List telefonos

    // … constructors and methods
    }

    public class Telefono{
    private String Codigo;
    private String numero;
    // … constructors and methods
    }

    este seria el xml que recibo :

    Joe Walnes

    011
    444555

    011
    3366655

    al deserealizar me devuelve el objecto Person con un array que contiene objectos de tipo Telefono pero con los atributos un null.

    Alguna idea..?
    Muchas gracias, saludos Victor

    • cirovladimir Says:

      Pues lo utilizo de la siguiente forma y no he tenido problemas.

      public class Reporte {
          
          private String nombre;
          private List consultas;
          
          public void setNombre(String nombre) {
              this.nombre = nombre;
          }
          public String getNombre() {
              return nombre;
          }
          public void setConsultas(List consultas) {
              this.consultas = consultas;
          }
          public List getConsultas() {
              if(this.consultas==null)
                  this.consultas=new ArrayList();
              return consultas;
          }
          
          public Reporte() {
          }
         
          public void saveXML(String filePath) throws Exception{
          	XStream xstream=new XStream();
          	xstream.alias("reporte", Reporte.class);
          	xstream.alias("consulta", Consulta.class);
              FileWriter xmlFile=new FileWriter(filePath);
              xstream.toXML(this,xmlFile);
          }
          public static Reporte fromXML(String filePath) throws Exception{
          	XStream xstream=new XStream();
          	xstream.alias("reporte", Reporte.class);
          	xstream.alias("consulta", Consulta.class);
          	return (Reporte)xstream.fromXML(new FileReader(filePath));
          }
      }
      
      public class Consulta {
      
          private String nombre;
          private String sql;
          
          public void setNombre(String nombre) {
              this.nombre = nombre;
          }
          public String getNombre() {
              return nombre;
          }
          public void setSql(String sql) {
              this.sql = sql;
          }
          public String getSql() {
              return sql;
          }
      
          public Consulta() {
          }    
      }
      

      con este XML

      <reporte>
         <nombre>Reporte</nombre>
         <consultas>
            <consulta>
               <nombre>Consulta 0</nombre>
               <sql>
               	SELECT SYSDATE
               	FROM DUAL
               </sql>
            </consulta>
            <consulta>
               <nombre>Consulta 1</nombre>
               <sql>
               	SELECT SYSDATE
               	FROM DUAL
               </sql>
            </consulta>
            <consulta>
               <nombre>Consulta 2</nombre>
               <sql>
               	SELECT SYSDATE
               	FROM DUAL
               </sql>
            </consulta>
         </consultas>
      </reporte>
      
  2. Ismael Says:

    Yo tengo el siguient el problema, adjunto el codigo que tengo:

    import java.util.ArrayList;
    import java.util.List;

    public class Persona {

    private String nombre;
    private String apellidos;
    private List documento = new ArrayList();

    private Coche coche;

    public Persona() {
    }
    }

    //////////////////////////////////////////

    public class Documento {

    private String numero;
    private String tipo;

    public Documento() {
    }
    }

    ////////////////////////////////////////

    Mi problema es que no me acepta el atributo List, me dice :

    Severity and Description Path Resource Location Creation Time Id
    documento cannot be resolved pruebaxstream/src Persona.java line 39 1252599598538 233023
    documento cannot be resolved or is not a field pruebaxstream/src Persona.java line 43 1252599598538 233025
    The type ArrayList is not generic; it cannot be parameterized with arguments pruebaxstream/src Persona.java line 8 1252599598538 233021
    The type List is not generic; it cannot be parameterized with arguments pruebaxstream/src Persona.java line 8 1252599598538 233020
    The type List is not generic; it cannot be parameterized with arguments pruebaxstream/src Persona.java line 38 1252599598538 233022
    The type List is not generic; it cannot be parameterized with arguments pruebaxstream/src Persona.java line 42 1252599598538 233024

    Si alguien me puede ayudar se lo agradeceria muchisimo ya que estoy atascado, he probado con la version 1.4, 5.0 y 6.0 de java y no me funciona con ninguna.

    Muchas gracias.
    Un saludo

    • cirovladimir Says:

      The type ArrayList is not generic; it cannot be parameterized with arguments

      Tal vez este sea el problema.
      Has intentado utilizar genericos de la siguiente forma??

      private List<Documento> documento = new ArrayList<Documento>();

      Suerte!

      Nota: no se si el wordpress removio esa parte debido al simbolo menor que “<” y el mayor que “>”, en cuyo caso, tu problema seria otro.
      Porque no pruebas con el ejemplo del mensaje anterior 😉


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: