Serializando Datos Personalizados
Sin un método de serialización y deserialización, sus datos no se mantendrán a través de los reinicios. Sponge cuenta con 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 creationLos 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
yMap
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 usandogetSerializable (DataQuery, Class) `` o ``getSerializableList (DataQuery, Class) ``. Junto con la ruta, también debe especificar la ``Clase
del tipo serializable, comoHome.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») ``.
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 predeterminadoscreateFrom (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 decreate ()
. Si los datos son incompatibles con elDataHolder
, en su lugar debe devolverOptional.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)
.