JSON Serialization beyond limits in Unity

JSON Serialization

As we all know, JSON is the most widely used format for transferring data on the web. JSON is human-readable and easily machine parseable format. With the addition, Unity has a built-in JSON serialization class, which we can use for exchanging data across different technology. However, there are other techniques like XML, BSON, etc are used for data transferring also.

The JSON serialization and deserialization support by JsonUtility class by the unity. This JsonUtility class has supported any Monobehaviour, scriptable subclass as well as plain class/struct with the [Serializable] attribute.

However, when deserializing JSON into subclasses of MonoBehaviour or ScriptableObject, You just need to use FromjsonOverWrite method from JsonUtility class.

Besides this, it is necessary to know that JsonUtility class does not serialize types like Dictionary.

NOTE: We will discuss in upcoming paragraph, how to serialize dictionary beyond the limits of JsonUtility class.

JSON serialization and deserialization

For demonstrating JSON serialization and deserialization, we use a simple class called Player as follow.

[System.Serializable]
public class Player
{
    public string name;
    public int level;
    public bool selected;
    public float highscore;
}

The Player class has an [Serializable] attribute. So, JsonUtility recognizes as a valid class for serialization.

We can serialize the Player class to get the JSON data as output as follow.

using UnityEngine;

public class JsonOperation : MonoBehaviour
{
    void Start()
    {
        Player player = new Player
        {
            name = "Unity",
            level = 2,
            selected = true,
            highscore = 12.2f
        };

        //Serialziation of player class to JSON
        string json = JsonUtility.ToJson(player);
        Debug.Log(json);
    }
}

If you can run this script in the unity editor you will get the following result in the log console.

{"name":"Unity","level":2,"selected":true,"highscore":12.100000381469727}

As you show the float value of the high score is not accurate due to the encoding problem. You can change float to string to get an accurate value.

Deserialisation is the process of making data back to object. We already have a JsonOperaion class which used to serialize the data. Now on ad some deserialization code in it.

using UnityEngine;

public class JsonOperation : MonoBehaviour
{
    void Start()
    {
        Player player = new Player
        {
            name = "Unity",
            level = 2,
            selected = true,
            highscore = 12.1f
        };

        //Serialziation of player class to JSON
        string json = JsonUtility.ToJson(player);
        Debug.Log(json);

        Player player1 = new Player();
        player1 = JsonUtility.FromJson<Player>(json);
        Debug.Log("Name: " + player1.name);
    }
}

In the above code, we added another object called person1 to rectify the changes. The Result of the deserialization is saved into a person1 object using FromJson method. And if you run this script, you will get a player name in the console.

However, if you wish you can save/load this serialized data to/from file or used to communicate with the server.

Now, what if we have more than one player in the game and we want to save this data in JSON format in the file. So, let’s modified the JsonOperation class.

using System.Collections.Generic;

[System.Serializable]
public class PlayersList
{
    public List<Player> players = new List<Player>();
}

We have this new PlayerList class which contains the list of player we had in the game.

using UnityEngine;

public class JsonOperation : MonoBehaviour
{
    PlayersList playerList = new PlayersList();

    void Start()
    {
        playerList.players.Add(new Player
        {
            name = "Unity",
            level = 2,
            selected = true,
            highscore = 12.1f
        });

        playerList.players.Add(new Player
        {
            name = "John",
            level = 3,
            selected = true,
            highscore = 15f
        });

        //Serialziation of player class to JSON
        string json = JsonUtility.ToJson(playerList);
        Debug.Log(json);
    }
}

After running this script, you will get the following output.

{"players":[{"name":"Unity","level":2,"selected":true,"highscore":12.100000381469727},{"name":"John","level":3,"selected":true,"highscore":15.0}]}

Now, probably that only question running in your mind is what about the dictionary?. To serialize Dictionary in unity we need a custom serialization. The one solution is that we can use a custom class which acts as a dictionary item. And another solution is that we used custom JSON serializer.

Eliminate JsonUtility Limits

In Unity, we have a custom serializer called Json.Net for Unity. It is free to use. So, import it from the asset store in your project.

We will use the following class for dictionary serialization.

[System.Serializable]
public class PlayersDictionary
{
    public Dictionary<int, Player> playerDict = new Dictionary<int, Player>();
}

In PlayersDictionary class we saved the player with its key.

using UnityEngine;
using Newtonsoft.Json;

public class JsonOperation : MonoBehaviour
{
    PlayersDictionary playersDictionary = new PlayersDictionary();

    void Start()
    {
        playersDictionary.playerDict.Add(0, new Player
        {
            name = "Unity",
            level = 2,
            selected = true,
            highscore = 12f
        });

        playersDictionary.playerDict.Add(1, new Player
        {
            name = "John",
            level = 3,
            selected = true,
            highscore = 15f
        });

        //Serialziation of player class to JSON
        string json = JsonConvert.SerializeObject(playersDictionary);
        Debug.Log(json);
    }
}

Be in your mind that in the above code we used JSON.Net for serializing the dictionary. The result of the above script is,

{"playerDict":{"0":{"name":"Unity","level":2,"selected":true,"highscore":12.0},"1":{"name":"John","level":3,"selected":true,"highscore":15.0}}}

In Conclusion, We can say that JSON serialization is versatile among the platforms. Although the built-in JsonUtility class is not fully compatible with all objects, as we’ve seen in this post, you can easily overcome by using some custom serializer like Json.Net.

Leave a Reply