Serialización de Datos
Mientras un ImmutableDataManipulator es una buena manera de almacenar datos mientras el servidor está ejecutándose, no persistirá durante el reinicio. Sin embargo, cada implemento DataManipulator de la interfaz :javadoc:`DataSerializable`y así puede ser serializado a un :javadoc:`DataContainer` y deserailizado a un DataBuilder.
Después de esta conversación inicial del DataManipulator
especializado para una estructura más general, el DataContainer
se puede seguir procesando.
DataContainer y DataView
Un DataView es una estructura de propósito general para almacenar cualquier tipo de datos. Soporta múltiples valores e incluso anida DataView
s como un valor, así permite una estructura de árbol. Cada valor es identificado por un DataQuery. Un DataContainer
es una raíz DataView
.
Cada DataSerializable
proporciona un método toContainer()
que creará y devolverá un DataContainer
. Como un ejemplo, llamando toContainer()
en una instancia HealthData producirá un DataContainer
que contiene dos valores, uno para el estado actual y uno para la salud máxima, cada uno identificado por el DataQuery
de la respectiva Llave
.
import org.spongepowered.api.data.DataContainer;
import org.spongepowered.api.data.key.Keys;
DataContainer serializedHealth = healthData.toContainer();
double currentHealth = serializedHealth.getDouble(Keys.HEALTH.getQuery()).get();
currentHealth == healthData.health().get(); // true
Convertir este contenedor de vuelta a una instancia HealthData
se realiza por el``DataBuilder`` correspondiente. Esos son registrados y administrados por el DataManager. También puede ser obtenido por una instancia válida de :javadoc:`Juego` o utilizando la clase de utilidad Sponge. El DataManager``proporciona un método para obtener el apropiado ``DataBuilder
para deserializar una clase dada y adicionalmente un método abreviado para obtener el DataBuilder
y hacer que realice la deserialización en un solo paso. Los siguientes dos ejemplos de código son funcionalmente equivalentes.
Ejemplo de Código: Deserialización, la manera larga
import org.spongepowered.api.data.DataView;
import org.spongepowered.api.data.manipulator.mutable.entity.HealthData;
import org.spongepowered.api.util.persistence.DataBuilder;
import java.util.Optional;
public Optional<HealthData> deserializeHealth(DataView container) {
final Optional<DataBuilder<HealthData>> builder = Sponge.getDataManager().getBuilder(HealthData.class);
if (builder.isPresent()) {
return builder.get().build(container);
}
return Optional.empty();
}
Ejemplo de Código: Deserialización, la manera corta
import org.spongepowered.api.data.manipulator.mutable.entity.HealthData;
public Optional<HealthData> deserializeHealth(DataView container) {
return Sponge.getDataManager().deserialize(HealthData.class, container);
}
La función deserializeHealth
devolverá Optional.empty()` si no hay ``DataBuilder` registrado para ``HealthData
o el DataContainer
suministrado está vacío. Si datos inválidos están presentes en el DataContainer
, una InvalidDataException se producirá.
DataTranslator
En Sponge, generalmente las implementaciones MemoryDataView y MemoryDataContainer son utilizadas, las cuales residen solo en la memoria y así no persistirán después de reiniciar el servidor. Con el fin de almacenar persistentemente un DataContainer
, primero tiene que ser convertido en una representación almacenable.
Utilizando la implementación DataTranslators#CONFIGURATION_NODE para DataTranslator, podemos convertir un DataView
en un ConfigurationNode y viceversa. ConfigurationNode
s puede entonces ser escrito y leído por un archivo persistente utilizando la Biblioteca de Configuración.
Ejemplo de Código: Serializar una instancia HealthData para Configuración
import ninja.leaping.configurate.ConfigurationNode;
import org.spongepowered.api.data.persistence.DataTranslator;
import org.spongepowered.api.data.persistence.DataTranslators;
public ConfigurationNode translateToConfig(HealthData data) {
final DataTranslator<ConfigurationNode> translator = DataTranslators.CONFIGURATION_NODE;
final DataView container = data.toContainer();
return translator.translate(container);
}
Ejemplo de Código: Deserializar una instancia HealthData desde Configuración
import java.util.Optional;
public Optional<HealthData> translateFromConfig(ConfigurationNode node) {
final DataTranslator<ConfigurationNode> translator = DataTranslators.CONFIGURATION_NODE;
final DataView container = translator.translate(node);
return deserializeHealth(container);
}