Serialization Methods
Serialization is the process of turning runtime objects into text or binary data that can be transferred and stored, and then read back into a runtime object at a later time. For uGameDB, this is a central concept because you always work with complex types in your game and you need an easy way to store these objects in the database. Whenever you use the read and write operations in uGameDB, such as Bucket.Get() and Bucket.Set(), the underlying system will try its best to serialize and deserialize the runtime type that you specify. For many simple system types this will work right out of the box. Reading and writing instances of your own custom types is also easy, but you need to register a codec for that type with the serialization library. The codec consists of two callback methods that the system will invoke when it wants to serialize or deserialize instances of your specific type. uGameDB supports serialization to two different data formats, JSON and BitStream. You specify which data format, or encoding, you want to use when you write your data. The encoding is stored along with the data and will be found out automatically when you read it back again. Regardless of which encoding you choose, the pattern of registering a codec for your type will be the same.JSON Encoding
JSON (JavaScript Object Notation) is a format for expressing general-purpose data as text, that borrows its syntax from JavaScript objects. It has similar properties to XML in that it allows you to express nested data structures with members of various data types. JSON data usually becomes shorter than XML data because of the lack of named closing tags. People also tend to prefer JSON data because it is relatively easy for humans to read. JSON works very well together with Riak, because it is possible to examine and filter the data within the database when making MapReduce queries. You should always use the JSON encoding unless you have very specific reasons to use BitStream instead. In order to perform JSON serialization, uGameDB uses the Jboy JSON library. You can read a lot more about this at the Jboy manual page. This also contains all the details on how to register JSON codecs that uGameDB can use. In short, you register a codec using Jboy.Json.AddCodec<T>() with a Jboy.JsonSerializer and a Jboy.JsonDeserializer callback. Note: The Jboy library is a new addition to uGameDB and is only available in the uGameDB 1.1 Beta. By performing the following steps, you will be able to store any class through uGameDB as JSON data.- Define your own class, for example with the name MyClass, and implement the JsonSerializer and JsonDeserializer callbacks. These callbacks can be static methods in your class to keep a clean organization.
- Register a JSON codec by calling Jboy.Json.AddCodec<MyClass>(), with your callbacks as arguments.
- Call uGameDB.Bucket.Set() with the encoding parameter set to uGameDB.Encoding.Json. This will write an instance of MyClass to the database encoded as JSON. uGameDB will call your registered serializer callback to serialize the supplied instance.
- Whenever you call uGameDB.Bucket.Get() to read the JSON-encoded data back, uGameDB will automatically identify it as JSON and will use your registered deserializer callback to create a MyClass instance from the data.
IEnumerator ReadWriteJsonExample()
{
Jboy.Json.AddCodec<Person>(Person.JsonSerializer, Person.JsonDeserializer);
var bucket = new uGameDB.Bucket("people"); var writePerson = new Person("Steve", "Johnson", 35);
var setRequest = bucket.Set("steve", writePerson, uGameDB.Encoding.Json); yield return setRequest.WaitUntilDone(); Debug.Log("Successfully wrote person: " + writePerson);
var getRequest = bucket.Get("steve"); yield return getRequest.WaitUntilDone(); var readPerson = getRequest.GetValue<Person>(); Debug.Log("Successfully read person: " + readPerson); }
public class Person { private string _firstName; private string _lastName; private int _age;
public Person() {}
public Person(string firstName, string lastName, int age) { _firstName = firstName; _lastName = lastName; _age = age; }
public static void JsonSerializer(Jboy.JsonWriter writer, object instance) { var person = (Person) instance; writer.WriteObjectStart(); writer.WritePropertyName("firstName"); writer.WriteString(person._firstName); writer.WritePropertyName("lastName"); writer.WriteString(person._lastName); writer.WritePropertyName("age"); writer.WriteNumber(person._age); writer.WriteObjectEnd(); }
public static object JsonDeserializer(Jboy.JsonReader reader) { var person = new Person(); reader.ReadObjectStart(); reader.ReadPropertyName("firstName"); person._firstName = reader.ReadString(); reader.ReadPropertyName("lastName"); person._lastName = reader.ReadString(); reader.ReadPropertyName("age"); person._age = (int) reader.ReadNumber(); reader.ReadObjectEnd(); return person; }
public override string ToString() { return "Person: First name: " + _firstName + ", Last name: " + _lastName + ", Age: " + _age; } }
var bucket = new uGameDB.Bucket("people"); var writePerson = new Person("Steve", "Johnson", 35);
var setRequest = bucket.Set("steve", writePerson, uGameDB.Encoding.Json); yield return setRequest.WaitUntilDone(); Debug.Log("Successfully wrote person: " + writePerson);
var getRequest = bucket.Get("steve"); yield return getRequest.WaitUntilDone(); var readPerson = getRequest.GetValue<Person>(); Debug.Log("Successfully read person: " + readPerson); }
public class Person { private string _firstName; private string _lastName; private int _age;
public Person() {}
public Person(string firstName, string lastName, int age) { _firstName = firstName; _lastName = lastName; _age = age; }
public static void JsonSerializer(Jboy.JsonWriter writer, object instance) { var person = (Person) instance; writer.WriteObjectStart(); writer.WritePropertyName("firstName"); writer.WriteString(person._firstName); writer.WritePropertyName("lastName"); writer.WriteString(person._lastName); writer.WritePropertyName("age"); writer.WriteNumber(person._age); writer.WriteObjectEnd(); }
public static object JsonDeserializer(Jboy.JsonReader reader) { var person = new Person(); reader.ReadObjectStart(); reader.ReadPropertyName("firstName"); person._firstName = reader.ReadString(); reader.ReadPropertyName("lastName"); person._lastName = reader.ReadString(); reader.ReadPropertyName("age"); person._age = (int) reader.ReadNumber(); reader.ReadObjectEnd(); return person; }
public override string ToString() { return "Person: First name: " + _firstName + ", Last name: " + _lastName + ", Age: " + _age; } }
BitStream Encoding
uGameDB supports BitStream encoding of the same format that uLink does. BitStream is a highly customizable binary encoding format that allows you to pack your data in any way you want. The benefit is that you can store large amounts of data very efficiently. The drawback is that your data will appear as a an unknown binary chunk to Riak and to anyone else reading it. This, for example, makes it very difficult to inspect and filter the data during a MapReduce request.A rule of thumb is to only use BitStream encoding with uGameDB when you specifically need it, like when you are storing big objects that you only read and write. When in doubt, go with JSON encoding.
For a detailed discussion about the BitStream format, see the Serialization and Data Types chapter in the uLink manual.
BitStream also require you to register a codec before reading and writing your own type. The following code works on the same data as the JSON example above, and shows how it would look when using BitStream encoding. Just like the previous example, this one assumes that you are connected to Riak before starting the coroutine.
Despite their similarity, the BitStream classes in uGameDB are not the same as the ones in uLink. Therefore you may have to qualify the BitStream and BitStreamCodec classes with the uGameDB namespace, if you are using uGameDB and uLink together.
IEnumerator ReadWriteBitStreamExample()
{
uGameDB.BitStreamCodec.Add<Person>(Person.BitStreamDeserializer,
Person.BitStreamSerializer);
var bucket = new uGameDB.Bucket("people"); var writePerson = new Person("Steve", "Johnson", 35);
var setRequest = bucket.Set("steve", writePerson, uGameDB.Encoding.Bitstream); yield return setRequest.WaitUntilDone(); Debug.Log("Successfully wrote person: " + writePerson);
var getRequest = bucket.Get("steve"); yield return getRequest.WaitUntilDone(); var readPerson = getRequest.GetValue<Person>(); Debug.Log("Successfully read person: " + readPerson); }
public class Person { private string _firstName; private string _lastName; private int _age;
public Person() {}
public Person(string firstName, string lastName, int age) { _firstName = firstName; _lastName = lastName; _age = age; }
public static void BitStreamSerializer(uGameDB.BitStream stream, object instance, params object[] args) { var person = (Person) instance; stream.Write(person._firstName); stream.Write(person._lastName); stream.Write(person._age); }
public static object BitStreamDeserializer(uGameDB.BitStream stream, params object[] args) { var person = new Person(); person._firstName = stream.Read<string>(); person._lastName = stream.Read<string>(); person._age = stream.Read<int>(); return person; }
public override string ToString() { return "Person: First name: " + _firstName + ", Last name: " + _lastName + ", Age: " + _age; } }
var bucket = new uGameDB.Bucket("people"); var writePerson = new Person("Steve", "Johnson", 35);
var setRequest = bucket.Set("steve", writePerson, uGameDB.Encoding.Bitstream); yield return setRequest.WaitUntilDone(); Debug.Log("Successfully wrote person: " + writePerson);
var getRequest = bucket.Get("steve"); yield return getRequest.WaitUntilDone(); var readPerson = getRequest.GetValue<Person>(); Debug.Log("Successfully read person: " + readPerson); }
public class Person { private string _firstName; private string _lastName; private int _age;
public Person() {}
public Person(string firstName, string lastName, int age) { _firstName = firstName; _lastName = lastName; _age = age; }
public static void BitStreamSerializer(uGameDB.BitStream stream, object instance, params object[] args) { var person = (Person) instance; stream.Write(person._firstName); stream.Write(person._lastName); stream.Write(person._age); }
public static object BitStreamDeserializer(uGameDB.BitStream stream, params object[] args) { var person = new Person(); person._firstName = stream.Read<string>(); person._lastName = stream.Read<string>(); person._age = stream.Read<int>(); return person; }
public override string ToString() { return "Person: First name: " + _firstName + ", Last name: " + _lastName + ", Age: " + _age; } }






