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 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
Whenever you’re reading a serialized object, it’s tempting to read all the individual values yourself in order to manually create all the required objects (and their parameters) for your data. However, depending on the data saved in the container there are a few ways that are far more convenient:
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;
private String name = "Spongie";
@Override
public DataContainer toContainer() {
return DataContainer.createNew()
.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
.
You’ll want to check that all the queries you want to retrieve are present using DataView.contains(Key...)
. If not,
the data is likely incomplete and you should return 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
.
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
import org.spongepowered.api.data.persistence.DataContentUpdater
import 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
.
As with other data, ensure that you register the translator during GameRegistryEvent.Register<DataTranslator<?>>
.