Serializing Data

Sementara ImmutableDataManipulator merupakan cara yang baik untuk menyimpan data saat server sedang berjalan, tidak akan bertahan selama mengulang kembali. Bagaimanapun, setiap DataManipulator mengimplementasikan interface DataSerializable sehingga dapat diserialkan ke DataContainer dan dibuat tidak serial lagi oleh DataBuilder.

Setelah konversi awal ini dari DataManipulator khusus ke struktur yang lebih umum, DataContainer dapat diproses lebih lanjut.

Wadah Data dan Tampilan Data

DataView adalah struktur umum untuk memegang semua jenis data. Mendukung beberapa nilai dan bahkan DataViews bersarang sebagai suatu nilai, sehingga mengizinkan untuk struktur seperti-tree. Setiap nilai diidentifikasikan oleh DataQuery. DataContainer merupakan akar DataView.

Setiap DataSerializable menyediakan metode toContainer() yang akan membuat dan mengembalikan DataContainer. Sebagai contoh, memanggil toContainer() pada sebuah instance HealthData akan menghasilkan sebuah DataContainer yang berisi dua nilai, satu untuk kesehatan saat ini dan satu untuk kesehatan maksimal, masing-masing diidentifikasi oleh DataQuery yang berhubungan dengan Key.

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

Mengkonversi container ini kembali ke instance HealthData dilakukan oleh DataBuilder yang sesuai. itu didaftarkan dan dikelola oleh DataManager. Dapat diperoleh salah satunya dari sebuah instance Game yang valid atau menggunakan kelas utilitas Sponge. DataManager menyediakan sebuah metode untuk mendapatkan DataBuilder yang sesuai memisahkan serial kelas yang diberikan dan tambahan metode singkat untuk mendapatkan DataBuilder dan membuatnya melakukan pemisahan serial dalam satu langkah. Kedua contoh berikut sama secara fungsional.

Kode Contoh: Deserialization, jalan panjang

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();
}

Kode Contoh: Deserialization, cara singkat

import org.spongepowered.api.data.manipulator.mutable.entity.HealthData;

public Optional<HealthData> deserializeHealth(DataView container) {
    return Sponge.getDataManager().deserialize(HealthData.class, container);
}

DeserializeHealth fungsi akan kembali Optional.kosong() jika tidak ada DataBuilder terdaftar HealthData...` atau disediakan ``DataContainer adalah kosong. Jika data yang tidak valid hadir dalam DataContainer, InvalidDataException akan dilemparkan.

DataTranslator

Dalam Spons, umumnya implementasi MemoryDataView dan MemoryDataContainer yang digunakan, yang berada di memori saja dan dengan demikian tidak akan bertahan lebih dari satu server restart. Dalam rangka untuk terus-menerus menyimpan DataContainer, hal pertama yang harus diubah menjadi storable representasi.

Menggunakan DataTranslators#CONFIGURATION_NODE pelaksanaan DataTranslator, kita dapat mengkonversi DataView ke ConfigurationNode dan sebaliknya. ConfigurationNodes kemudian dapat dibaca dan ditulis gigih file menggunakan Configurate Perpustakaan.

** Kode Contoh: Serializing contoh HealthData untuk configurate **

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);
}

** Contoh Kode: Deserializing contoh HealthData dari Configurate **

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);
}

Format Data

Alternatif untuk menggunakan DataTranslator adalah dengan menggunakan DataFormat, yang memungkinkan anda untuk menyimpan DataContainer di HOCON, JSON atau NBT format. Anda juga dapat menciptakan Datakontainer menggunakan DataFormat. Spons yang disediakan DataFormat implementasi tersedia di DataFormat kelas.

Sebagai contoh, kita dapat menggunakan DataFormat#JSON DataFormat yang memungkinkan kita untuk membuat JSON representasi dari Datakontainer. Pengeluaran JSON kemudian bisa dengan mudah disimpan dalam database. Kita kemudian dapat menggunakan yang sama DataFormat untuk menciptakan asli Datakontainer dari JSON ini bila diperlukan.

Impor untuk contoh kode

import org.spongepowered.api.Sponge;
import org.spongepowered.api.data.DataContainer;
import org.spongepowered.api.data.persistence.DataFormats;
import org.spongepowered.api.item.inventory.ItemStackSnapshot;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

** Contoh Kode: Serializing sebuah ItemStackSnapshot ke format JSON **

String json = DataFormats.JSON.write(itemStack.toContainer());

** Contoh Kode: Deserializing sebuah ItemStackSnapshot dari format JSON **

DataContainer container = DataFormats.JSON.read(json);

** Contoh Kode: Menulis sebuah ItemStackSnapshot ke file menggunakan NBT **

public void writeItemStackSnapshotToFile(ItemStackSnapshot itemStackSnapshot, Path path) {
    DataContainer dataContainer = itemStackSnapshot.toContainer();
    try (OutputStream outputStream = Files.newOutputStream(path)) {
        DataFormats.NBT.writeTo(outputStream, dataContainer);
    } catch (IOException e) {
        // For the purposes of this example, we just print the error to the console. However,
        // as this exception indicates the file didn't save, you should handle this in a way
        // more suitable for your plugin.
        e.printStackTrace();
    }
}

** Contoh Kode: Membaca ItemStackSnapshot dari sebuah file menggunakan NBT **

public Optional<ItemStackSnapshot> readItemStackSnapshotFromFile(Path path) {
    try (InputStream inputStream = Files.newInputStream(path)) {
        DataContainer dataContainer = DataFormats.NBT.readFrom(inputStream);
        return Sponge.getDataManager().deserialize(ItemStackSnapshot.class, dataContainer);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return Optional.empty();
}