XML Serialization and Deserialization in C# Using Unity

XML Serialization

What is XML serialization and Deserialization?

In this article, we will discuss how to save structural data using XML serialization. Most of the game developer was saving their data on the device using playerPrefs. But the main problem with this is, it is not human-readable and other application might not aware how it is saved.

More often we need to communicate to the server or any other application by means we need one data structure that is common and understandable for all technology. Though there are many solutions for data saving in unity, such as JSON or SQL and XML. However, XML is the easiest to read and implement.

XML serialization is the process of converting an object into the XML format. On the other hand, deserialization is the process of converting the XML format to its object.

This XML format can be saved in the device and can be opened in any text editor. You can even see what data is being saved in the XML file through it is human readable. So, the XML file has an extension and structure for data saving. C# already has a tool for serialization.

Before starting the serialization, it is necessary to remember the following two points.

  1. Only public fields can be serialized using XML serialization.
  2. The serialized class have a parameterless constructor.

We are using the following class for our XML serialization.

public class Gun
{
    public string Name;
    public bool Zoomable;
    public int Ammo;
    public float RecoilTime;
}

Here is the default serialization of the above class.

using System.IO;
using UnityEngine;

public class Serializer : MonoBehaviour
{
    void Start()
    {
        Gun gun = new Gun
        {
            Name = "AK47",
            Zoomable = true,
            Ammo = 30,
            RecoilTime = 0.5f
        };

        XmlOperation.Serialize(gun, Path.Combine(Application.persistentDataPath, "Gun.xml"));
    }
}

You can find XmlOperation class at the bottom of this article.

Output:

<?xml version="1.0"?>
<Gun xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Name>AK47</Name>
  <Zoomable>true</Zoomable>
  <Ammo>30</Ammo>
  <RecoilTime>0.5</RecoilTime>
</Gun>

Attributes in XML Serialization

To serialized any class using serialization, we need to modify a class with the XML attributes. Following are some most important attributes used for serialization.

  • [XmlElement]
  • [XmlAttributes]
  • [XmlIgnore]
  • [XmlRoot]
  • [XmlArray]
  • [XmlArrayItem]

Now let’s see all attributes in details.

[XmlElement(String)]

All the public fields in the object are serialized as an XmlElement. You can use it to change the name of the field. Let’s see how can we use it.

using System.Xml.Serialization;

public class Gun
{
    [XmlElement("GunName")]
    public string Name;
    public bool Zoomable;
    public int Ammo;
    public float RecoilTime;
}

In the above code, we changed the Field “Name” to “GunName”.

Output:

<?xml version="1.0"?>
<Gun xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <GunName>AK47</GunName>
  <Zoomable>true</Zoomable>
  <Ammo>30</Ammo>
  <RecoilTime>0.5</RecoilTime>
</Gun>

[XmlAttributes]

By using this attribute, the class field will be represented as an XML attribute.

using System.Xml.Serialization;

public class Gun
{
    [XmlElement("GunName")]
    public string Name;
    [XmlAttribute("Zoom")]
    public bool Zoomable;
    public int Ammo;
    public float RecoilTime;
}

Output:

<?xml version="1.0"?>
<Gun xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Zoom="true">
  <GunName>AK47</GunName>
  <Ammo>30</Ammo>
  <RecoilTime>0.5</RecoilTime>
</Gun>

[XmlIgnore]

All public fields will be serialized by default. If we want to ignore some public field in the serialization, we can use this attribute.

using System.Xml.Serialization;

public class Gun
{
    [XmlElement("GunName")]
    public string Name;
    [XmlAttribute("Zoom")]
    public bool Zoomable;
    [XmlIgnore]
    public int Ammo;
    public float RecoilTime;
}

Output:

<?xml version="1.0"?>
<Gun xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Zoom="true">
  <GunName>AK47</GunName>
  <RecoilTime>0.5</RecoilTime>
</Gun>

[XmlRoot(String)]

By default, the class name will be the Root name in the XML and we can change this by using this attribute.

using System.Xml.Serialization;

[XmlRoot("MyGun")]
public class Gun
{
    [XmlElement("GunName")]
    public string Name;
    [XmlAttribute("Zoom")]
    public bool Zoomable;
    [XmlIgnore]
    public int Ammo;
    public float RecoilTime;
}

Output:

<?xml version="1.0"?>
<MyGun xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Zoom="true">
  <GunName>AK47</GunName>
  <RecoilTime>0.5</RecoilTime>
</MyGun>

[XmlArray(String)]

There is more than one gun in the games. So, we created a GunsContainer class with the list of guns as following.

using System.Collections.Generic;
using System.Xml.Serialization;

public class GunsContainer
{
    [XmlArray("Guns")]
    public List<Gun> gunsContainers = new List<Gun>();
}

Note that the list has an [XmlArray] attribute and we used this class as followed to get the output.

using System.IO;
using UnityEngine;

public class Serializer : MonoBehaviour
{
    void Start()
    {
        GunsContainer gunsContainer = new GunsContainer();

        gunsContainer.gunsContainers.Add(new Gun
        {
            Name = "AK47",
            Zoomable = true,
            Ammo = 30,
            RecoilTime = 0.5f
        });

        gunsContainer.gunsContainers.Add(new Gun
        {
            Name = "Sniper",
            Zoomable = true,
            Ammo = 15,
            RecoilTime = 0.8f
        });

        XmlOperation.Serialize(gunsContainer, Path.Combine(Application.persistentDataPath, "Guns.xml"));
    }
}

And the output will be:

<?xml version="1.0"?>
<GunsContainer xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Guns>
    <Gun>
      <Name>AK47</Name>
      <Zoomable>true</Zoomable>
      <Ammo>30</Ammo>
      <RecoilTime>0.5</RecoilTime>
    </Gun>
    <Gun>
      <Name>Sniper</Name>
      <Zoomable>true</Zoomable>
      <Ammo>15</Ammo>
      <RecoilTime>0.8</RecoilTime>
    </Gun>
  </Guns>
</GunsContainer>

[XmlArrayItem(String)]

This attribute used to modify the name of the array item.

using System.Collections.Generic;
using System.Xml.Serialization;

public class GunsContainer
{
    [XmlArray("Guns")]
    [XmlArrayItem("MyGun")]
    public List<Gun> gunsContainers = new List<Gun>();
}

Output:

<?xml version="1.0"?>
<GunsContainer xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Guns>
    <MyGun>
      <Name>AK47</Name>
      <Zoomable>true</Zoomable>
      <Ammo>30</Ammo>
      <RecoilTime>0.5</RecoilTime>
    </MyGun>
    <MyGun>
      <Name>Sniper</Name>
      <Zoomable>true</Zoomable>
      <Ammo>15</Ammo>
      <RecoilTime>0.8</RecoilTime>
    </MyGun>
  </Guns>
</GunsContainer>

We have discussed all the important attributes in serialization. Moreover, Its time to know how to Serialize/Deserialize the XML file in unity using C#.

XML Serialization/Deserialization

We discussed what serialization and deserialization are at the beginning of the article. Now we are implementing it using C#.

using System.IO;
using System.Xml.Serialization;

public static class XmlOperation
{
    public static void Serialize(object item, string path)
    {
        XmlSerializer serializer = new XmlSerializer(item.GetType());
        StreamWriter writer = new StreamWriter(path);
        serializer.Serialize(writer.BaseStream, item);
        writer.Close();
    }

    public static T Deserialize<T>(string path)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        StreamReader reader = new StreamReader(path);
        T deserialized = (T)serializer.Deserialize(reader.BaseStream);
        reader.Close();
        return deserialized;
    }
}

In conclusion, we can say that XML Serialization in unity is pretty easy and human-readable. All you have to do is modify the class based on your requirement.

Leave a Reply