-
Notifications
You must be signed in to change notification settings - Fork 2
Special cases
While Serializer
is very general in nature and works for most types of objects, there are certain types that it just cannot (de)serialize due to their fundamental nature. Examples of such types are unmanaged types (string
, char
, bool
, numeric types like int
, float
, etc), collections, arrays, and so on.
GDSerializer handles the (de)serialization of these types by utilising more specialized implementations of ISerializer
, designed to work for very specific types only.
Serializer
knows about these specific serializer implementations, and so whenever it encounters a type that it cannot (de)serialize, it will automatically delegate the job to a more suitable serializer type.
The SimpleSerializer
class handles (de)serialization of most unmanaged types. This includes:
string
char
bool
sbyte
byte
short
ushort
int
uint
long
ulong
float
double
decimal
All of these are simply serialized as a single text node inside an element node, and deserialized by using the relevant Parse()
method.
For instance, the string "hello world"
would be serialized as:
<string>hello world</string>
The number 99
(int
) would be serialized as:
<int>99</int>
and so on.
Collections differ from most other types in the sense that they hold references to multiple other objects (usually of the same type). This means that Serializer
cannot be used to (de)serialize them, as it will have no way of iterating over the collection, or treating child XML nodes as separate items belonging to the collection.
The CollectionSerializer
class therefore handles (de)serialization of collections. More specifically, it can serialize and deserialize most types that implement ICollection<T>
.
Collections will be serialized as an XML node with multiple child nodes named item
. For example, a List<string>
containing the strings "hello"
and "world"
would be serialized as follows:
<Collection Type="System.Collections.Generic.List<string>">
<item>hello</item>
<item>world</item>
</Collection>
Arrays are a slightly more special kind of collection. Arrays do implement ICollection<T>
, but it is not possible to call Add(T)
on them as arrays have a fixed size. Moreover, arrays don't have a parameterless constructor (or any constructor for that matter) as they are special types.
The ArraySerializer
class therefore handles (de)serialization of arrays.
Like collections, arrays will also be serialized as an XML node with multiple child nodes named item
. For example, a string[]
containing the strings "hello"
and "world"
would be serialized as follows:
<Array Type="string[]">
<item>hello</item>
<item>world</item>
</Array>
Dictionaries are a slightly more special kind of collection. Technically, a type that implements IDictionary<TKey, TValue>
also implements ICollection<KeyValuePair<TKey, TValue>>
, but it cannot be (de)serialized by CollectionSerializer
as KeyValuePair<TKey, TValue>
has no parameterless constructor and no setters on its properties.
The DictionarySerializer
class therefore handles (de)serialization of most types that implement IDictionary<TKey, TValue>
.
Like collections, dictionaries will also be serialized as an XML node with multiple child nodes named item
. However, each item
node will have a child key
node and a child value
node, which will hold the key and value of the key-value pair. For example, a Dictionary<int, string>
containing the pairs (1, "one")
, (2, "two")
, and (3, "three")
would be serialized as follows:
<Dictionary Type="System.Collections.Generic.Dictionary<int,string>">
<item>
<key>1</key>
<value>one</value>
</item>
<item>
<key>2</key>
<value>two</value>
</item>
<item>
<key>3</key>
<value>three</value>
</item>
</Dictionary>
Note that if a field or property of an object is declared simply as an IDictionary<TKey, TValue>
, or typeof(IDictionary<TKey, TValue>)
is passed to the serializer as the optional type argument, it will (de)serialize using Dictionary<TKey, TValue>
as the concrete type.
Not to be confused with enum
.
In many cases, it may be desirable to expose a field or property as an IEnumerable<T>
rather than a collection or a more concrete type. In this case, CollectionSerializer
cannot help again - but EnumerableSerializer
can.
If a field or property is declared simply as an IEnumerable<T>
, or typeof(IEnumerable<T>)
is passed to the serializer as the optional type argument, it will automatically (de)serialize it as a List<T>
. In other words, members declared simply as IEnumerable<T>
will be treated as List<T>
.
Not to be confused with enumerables (IEnumerable<T>
).
Enums are special cases of integers with names associated with them. An enum
is technically an unmanaged type, but is not handled by SimpleSerializer
. Instead, the EnumSerializer
class handles the (de)serialization of enums.
An enum
is serialized in XML as the string representation of its integer value. For example, the value Day.Tuesday
in enum Day { Monday, Tuesday, ..., Sunday }
would be serialized as follows:
<Day>Tuesday</Day>
Most Godot nodes already fit the requirements to be (de)serialized by the default ISerializer
implementation - Serializer
. However, this does not allow their children to be (de)serialized, as there is no writeable property or field in a Node
to set its children.
Therefore, the NodeSerializer
class handles the (de)serialization of nodes. Everything is done as if it was being (de)serialized by Serializer
- except for a node's children, which are (de)serialized using the <Children>
tag. For example, a Sprite
node named "Player" with a Tween
and an Area2D
named "Hitbox" as its children would be serialized like so:
<Godot.Sprite>
<Name>Player</Name>
<Children>
<item Type="Godot.Tween"/>
<item Type="Godot.Area2D">
<Name>Hitbox</Name>
</item>
</Children>
</Godot.Sprite>
- Certain types are special and cannot be (de)serialized through normal methods
- Specialized serializers are implemented to handle these types
-
Serializer
knows of the specialized serializers and will switch to using the appropriate one when it encounters such a type- This ensures that
Serializer
can be used everywhere without worrying about special cases as they will automatically be handled
- This ensures that
- Collections are (de)serialized by
CollectionSerializer
- Each item in the collection goes in an
item
node in the collection's XML node
- Each item in the collection goes in an
- Dictionaries are (de)serialized by
DictionarySerializer
- Each key-value pair in the dictionary goes in an
item
node, which has akey
node and avalue
node
- Each key-value pair in the dictionary goes in an
- Enumerables (not enums) are (de)serialized by
EnumerableSerializer
- They are treated as lists
- Like collections, each item goes in an
item
node
- Enums are (de)serialized by
EnumSerializer
- The string representation of the corresponding
enum
integer value is used
- The string representation of the corresponding
- Godot nodes are (de)serialized by
NodeSerializer
- All properties and fields are handled normally (as default)
- The children of a node go in the
Children
tag, which is treated as a collection of nodes