2011-01-05 13 views
5

Me pregunto cómo uso XMLEncoder para serializar ArrayList<foo> donde foo es mi propia clase.XMLEncoder en java para la serialización

¿Tengo que hacer algo en particular, es decir, definir primero mi propia estructura xml y luego llamar a String en cada valor de mi lista y escribirla?

¿Alguien me puede indicar un buen tutorial? http://java.sun.com/products/jfc/tsc/articles/persistence4/ Eso es lo que he estado viendo, pero no parece mencionar qué hacer con las clases que no son de la biblioteca.

Gracias

Respuesta

9

Si usted está buscando la serialización XML que sugeriría que se vaya para XStream

Person joe = new Person("Joe", "Walnes"); 
joe.setPhone(new PhoneNumber(123, "1234-456")); 
joe.setFax(new PhoneNumber(123, "9999-999")); 

String xml = xstream.toXML(joe); 

<person> 
    <firstname>Joe</firstname> 
    <lastname>Walnes</lastname> 
    <phone> 
    <code>123</code> 
    <number>1234-456</number> 
    </phone> 
    <fax> 
    <code>123</code> 
    <number>9999-999</number> 
    </fax> 
</person> 
10

no hay nada especial sobre la serialización de un ArrayList con XMLEncoder.

Aquí se muestra un ejemplo:

Hay una testBean clase bean:

public class TestBean { 

    private String name; 
    private int age; 

    public TestBean() { 
    this.name = ""; 
    this.age = 0; 
    } 

    public TestBean(String name, int age) { 
    this.name = name; 
    this.age = age; 
    } 

    // Getter and setter ... 

    @Override 
    public String toString() { 
    return String.format("[TestBean: name='%s', age=%d]", name, age); 
    } 
} 

y una clase principal, que serializar un ArrayList<TestBean> y la leyó de nuevo:

public class Main { 
    private static final String FILENAME = "testbeanlist.xml"; 

    public static void main(String[] args) { 
    try { 
     // Create a list of TestBean objects ... 
     final List<TestBean> list = new ArrayList<TestBean>(); 
     list.add(new TestBean("Henry", 42)); 
     list.add(new TestBean("Tom", 11)); 

     System.out.println("Writing list to file " + FILENAME + ": " + list); 

     // ... and serialize it via XMLEncoder to file testbeanlist.xml 
     final XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(
      new FileOutputStream(FILENAME))); 
     encoder.writeObject(list); 
     encoder.close(); 

     // Use XMLDecoder to read the same XML file in. 
     final XMLDecoder decoder = new XMLDecoder(new FileInputStream(FILENAME)); 
     final List<TestBean> listFromFile = (List<TestBean>) decoder.readObject(); 
     decoder.close(); 

     System.out.println("Reading list: " + listFromFile); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 
    } 
} 

Y luego el resultado es:

Writing list to file testbeanlist.xml: [[TestBean: name='Henry', age=42], [TestBean: name='Tom', age=11]] 
Reading list: [[TestBean: name='Henry', age=42], [TestBean: name='Tom', age=11]] 

El método toString() en TestBean es solo para impresión bonita. No influye en la serialización XML.

+0

He encontrado que esto no funcione, el ejemplo xstream funcionó muy bien aunque – Sara

+0

¿Qué es exactamente no funcionó para usted? Lo extraje del código de ejemplo de trabajo. ¿Implementaron los getters y setters en TestBean? Inserté solo un comentario apropiado para eso. – vanje

+0

Esta implementación funciona para las clases que están codificadas según la convención de JavaBeans, pero para las clases arbitrarias definidas por el usuario es necesario asegurarse de que XMLEncoder tenga instalados los PersistenceDelegates correctos. No todas las clases tienen propiedades, y no todas las propiedades son escribibles: cuanto más lejos esté su clase de la convención JavaBeans, más esfuerzo tendrá que hacer. – Johansensen

2

XMLEncoder se puede usar para cualquier clase, incluidas las definidas por el usuario; el artículo que menciona detalla cómo hacerlo, pero no está muy bien escrito, por lo que puede ser un poco difícil de entender.

Si la clase definida por el usuario sigue el JavaBeans spec, a continuación, puedes utilizar encoder.writeObject() para serializar una instancia List<Foo>. Esto se debe a que la salida XML es solo una serie de instrucciones sobre cómo recrear la instancia determinada en tiempo de ejecución. El predeterminado PersistenceDelegate sabe cómo serializar una estructura de lista, pero solo tiene un comportamiento predeterminado para las clases desconocidas. Por defecto, intenta recrear una instancia de objeto dada llamando a su constructor nullary (sin argumento) y luego configurando sus propiedades una por una a los valores de la instancia dada, algo que se garantiza que será posible si la clase es JavaBean.

Si su clase tiene algunas propiedades que son de solo lectura, es decir, las establece el constructor y no se pueden cambiar después del tiempo de construcción, entonces tiene que hacer (un poco) más para que funcione. Puede crear una instancia personalizada de DefaultPersistenceDelegate que reconozca su clase, y sepa cómo pasar los datos apropiados a su constructor; simplemente le pasa los nombres de las propiedades como una lista, y hará el resto:

PersistenceDelegate fooDelegate = new DefaultPersistenceDelegate(new String[] {"propertyName1", "propertyName2"}); 
encoder.setPersistenceDelegate(Foo.class, fooDelegate); 

Si su clase tiene argumentos de constructor que no se asignan directamente a propiedades con métodos getter, y/o existen otras complejidades para restaurar el estado del objeto, generalmente puede solucionarlos ampliando PersistenceDelegate e implementando el comportamiento necesario usted mismo.Sin embargo, si su clase es muy compleja de recrear en tiempo de ejecución y desea que se serialice, debe considerar seriamente rediseñarla para reducir su complejidad, esto hará que todo el proceso sea mucho más fácil y reducirá enormemente la posibilidad de errores, como además de facilitar el cambio y la ampliación en el futuro.

0

No estoy seguro de por qué tantos ejemplos en Internet son incompletos o no funcionan cuando solo les toma un poco de atención que sean mucho más útiles. Aquí hay un ejemplo completo que se puede implementar en un archivo (PersonBean.java) ¡y funciona!

// This example creates two PersonBeans, creates an ArrayList, adds the beans to the 
// list, serializes the ArrayList to an XML file. 
// It then loads from the XML file into a new ArrayList 
// 
// Keywords: ArrayList, Serialize, XMLEncode, XMLDecode 
// Note: Change the XML file while the 10 second Thread.sleep is waiting to see that 
// the data is actually loaded from the file. 

import java.io.FileOutputStream; 
import java.io.FileInputStream; 
import java.beans.XMLEncoder; 
import java.beans.XMLDecoder; 
import java.util.ArrayList; 

public class PersonBean { 
    private String name; 
    private int age; 

    public String getName() { 
    return name; 
    } 

    public int getAge() { 
    return age; 
    } 

    public void setName(String name) { 
    this.name = name; 
    } 

    public void setAge(int age) { 
    this.age = age; 
    } 

    @Override 
    public String toString() { 
    return String.format("[PersonBean: name='%s', age=%d]", name, age); 
    } 

    public static void main(String[] args) { 
    PersonBean person1 = new PersonBean(); 

    person1.setName("Joe"); 
    person1.setAge(30); 

    PersonBean person2 = new PersonBean(); 

    person2.setName("Jane"); 
    person2.setAge(25); 

    ArrayList arrayList1 = new ArrayList(); 
    arrayList1.add(person1); 
    arrayList1.add(person2); 

    try { 
     System.out.println("List 'arrayList1' = '" + arrayList1 + "'"); 
     FileOutputStream outputStream = new FileOutputStream("PersonBean.xml"); 
     XMLEncoder encoder = new XMLEncoder(outputStream); 
     encoder.writeObject(arrayList1); 
     encoder.close(); 
     Thread.sleep(10000); 
    } catch (Exception ex) { 
    } 

    try { 
     FileInputStream inputStream = new FileInputStream("PersonBean.xml"); 
     XMLDecoder decoder = new XMLDecoder(inputStream); 
     ArrayList<PersonBean> arrayList2 = (ArrayList<PersonBean>) decoder.readObject(); 
     decoder.close(); 
     System.out.println("List 'arrayList2' = '" + arrayList2 + "'"); 
    } catch (Exception ex) { 
    } 
    } 
} 
Cuestiones relacionadas