Serializando Datos Personalizados

Sin un método para serializar y deserializar, sus datos no se mantendrán durante los reinicios. Sponge tiene algunas formas diferentes de serializar/deserializar los datos según el tipo de datos:

  • DataSerializables implement an interface to perform serialization, and use DataBuilder for deserialization and creation

  • DataManipulators also implement DataSerializable, but instead use a DataManipulatorBuilder for deserialization and creation

  • Los objetos que no implementan o no pueden implementar `` DataSerializable`` usan :javadoc: DataTranslator para la serialización y la deserialización

Esto significa que prácticamente cualquier objeto en Java se puede guardar en el disco si ha sido registrado!

Lectura de DataViews

Cada vez que usted lee un objeto serializado, es tentador leer todos los valores individuales para crear manualmente todos los objetos requeridos (y sus parámetros) para sus datos. Sin embargo, dependiendo de los datos guardados en el contenedor, existen algunas formas que son mucho más convenientes:

  • Los tipos comunes de Java como int, String, double, List y Map se pueden recuperar utilizando los métodos integrados ``getInt(DataQuery) ``, ``getString(DataQuery) ``, etc. Las listas de estos tipos también se pueden recuperar de manera similar, por ejemplo ``getStringList(DataQuery) ``.

  • Los objetos DataSerializable pueden ser recuperados usando getSerializable (DataQuery, Class) `` o ``getSerializableList (DataQuery, Class) ``. Junto con la ruta, también debe especificar la ``Clase del tipo serializable, como Home.class.

  • Los objetos con un DataTranslator registrado se pueden recuperar utilizando getObject(DataQuery, Class) o ` getObjectList(DataQuery, Class) . Se puede encontrar una lista completa de las clases admitidas de manera predeterminada en :javadoc: `DataTranslators.

En todos los casos, debe especificar una ruta usando a :javadoc: DataQuery. Si sus datos tienen una Key correspondiente, esto es tan fácil como llamar a ``key.getQuery () ``. De lo contrario, la forma más fácil de hacerlo es con ``DataQuery.of («name») ``.

Truco

DataQueries se puede utilizar para hacer referencia a múltiples nodos de datos en un árbol al utilizar, por ejemplo, ``DataQuery.of(«my», «custom», «data») ``.

DataBuilders

Para hacer un objeto serializable, primero asegúrese de que implemente :javadoc: DataSerializable. Usted debe implementar solo dos métodos:

  • ``getContentVersion () `` - esto definió la versión actual de sus datos.

  • toContainer () `` - esto es lo que se le dará a su compilador cuando intente deserializar y objetar. Puede almacenar lo que desee en el ``DataContainer devuelto, siempre que también se pueda serializar utilizando uno de los métodos anteriores. Simplemente use el método ``set (DataQuery, Object) `` para guardar sus datos en la ruta dada.

Truco

Se recomienda que también guarde la versión de sus datos en el contenedor utilizando Queries.CONTENT_VERSION como consulta. Esto permitirá actualizaciones del control de versiones con :ref: content-updaters.

Ejemplo de Código: Implementando toContainer

import org.spongepowered.api.data.DataContainer;
import org.spongepowered.api.data.DataQuery;
import org.spongepowered.api.data.Queries;
import org.spongepowered.api.data.MemoryDataContainer;

String name = "Spongie";

@Override
public DataContainer toContainer() {
    return new MemoryDataContainer()
            .set(DataQuery.of("Name"), this.name)
            .set(Queries.CONTENT_VERSION, getContentVersion());
}

La siguiente parte es implementar un :javadoc: DataBuilder. Se recomienda extender :javadoc: AbstractDataBuilder ya que tratará de actualizar sus datos si la versión es menor a la versión actual. Solo hay un método que usted necesita implementar: `` build (DataView) , o `` buildContent(DataView) `` si usted está usando ``AbstractDataBuilder.

Deberá verificar que todas las consultas que desea recuperar estén presentes usando DataView.contains(Key...). Sino, es probable que los datos estén incompletos y usted debe devolver Optional.empty().

Si todo parece estar allí, utilice los métodos getX para construir los valores y devolver un objeto recién creado como un Optional.

Finalmente, debe registrar este compilador para que se pueda encontrar mediante extensiones. Para hacer esto, simplemente llame a DataManager#registerDataBuilder (Class, DataBuilder) haciendo referencia a la clase de datos y a una instancia del compilador.

DataContentUpdaters

¿Qué sucede si cambia el diseño de los datos en el lanzamiento de una nueva versión? :javadoc: DataContentUpdater s resuelve ese problema. Si el objeto serializado es menor que la versión actual, un AbstractDataBuilder intentará actualizar los datos antes de pasarlos al compilador.

Cada actualizador tiene una versión de entrada y una versión de salida. Debería tomar los datos anteriores y cambiar lo que sea necesario para actualizarlo a un diseño más nuevo. Si es imposible realizar la conversión debido a la falta de datos, es posible proveer un valor predeterminado que es interpretado en otro lugar - como por ejemplo, el compilador principal o el objeto en sí.

Finalmente, debe asegurarse de que todos los DataContentUpdater s se registren con ``DataManager#registerContentUpdater() `` haciendo referencia a la clase de datos principal, esto les permitirá a ellos ser descubiertos por el compilador.

Ejemplo de código: Implementando un DataContentUpdater

org.spongepowered.api.data.persistence.DataContentUpdater
org.spongepowered.api.text.Text

public class NameUpdater implements DataContentUpdater {

    @Override
    public int getInputVersion() {
        return 1;
    }

    @Override
    public int getOutputVersion() {
        return 2;
    }

    @Override
    public DataView update(DataView content) {
        String name = content.getString(DataQuery.of("Name")).get();

        // For example, version 2 uses a text for the name
        return content.set(DataQuery.of("Name"), Text.of(name));
    }
}

DataManipulatorBuilders

Un DataManipualatorBuilder es muy similar a DataBuilder, sin embargo, agrega algunos métodos directamente relacionados con los manipuladores de deserialización:

  • create () debería devolver un nuevo manipulador con valores predeterminados

  • createFrom (DataHolder) es similar al método de compilación, pero en su lugar los valores deben tomarse de DataHolder. Si no hay datos para tomar del titular, solo devuelva la salida de create (). Si los datos son incompatibles con el DataHolder, en su lugar debe devolver Optional.empty ().

Al igual que DataBuilder, debe leer y devolver su manipulador en el método `` build`` aplicable.

DataManipulatorBuilder s puede también usar DataContentUpdaters, siempre que implemente` AbstractDataBuilder`.

El registro de un DataManipulatorBuilder también es similar a DataBuilder pero utiliza el método register(). Usted debe hacer una referencia tanto a sus clases mutables como inmutables en el método, además de una instancia de su compilador.

Nota

Usted Debe hacer referencia a las clases de implementación si ha dividido la API de la implementación.

DataTranslators

A menudo, los objetos que desea serializar no son objetos que implementan DataSerializable, como `` Vector3d`` o `` Date``. Para permitir a estos objetos ustedimplementa un DataTranslator que maneje ambos, la serialización y deserialización del objeto.

La implementación de translate es idéntica a toContainer() y build(DataView) `` para un ``DataSerializable como se muestra arriba, excepto que se lanza un InvalidDataException si faltan datos en lugar de devolver un Optional.

Al igual que con otros datos, asegúrese de registrar el traductor con DataManager#registerTranslator(Class, DataTranslator).