[SOLVED] Deserialize JSON in Unity C#

Hi all,

I am sharing data between a python server and a unity C# client over a ZeroMQ socket. The idea is to send python objects like dictionary, list, tuple, etc. by first serializing them into a JSON string on python and then deserializing the JSON string into a serializable class on unity C# side. The communication works fine and I can verify the data sharing over the debug logs on both sides.

The problem is that I would like to deserialize the JSON string directly into a class and I am struggling with this part. For now, the JSON string I am receiving on unity C# is a simple python dict<string, string> i.e.

{"p1": "player1", "p2": "player2"}

Below is the class I use for storing the deserialized data in C#.

public class ParseReceivedData
    {
        public Dictionary<string, string> player_dict;
        //public List<string> p1_list;
        //public Tuple<string> p2_tuple;
        //public string actions_str;
        //public int states_num;

        public static ParseReceivedData CreateFromJSON(string jsonString)
        {
            return JsonUtility.FromJson<ParseReceivedData>(jsonString);
        }

        public void PrintOutput()
        {
            foreach (KeyValuePair<String, String> kvp in this.player_dict)
            {
                Debug.Log("Dict = {0} : {1}" + kvp.Key.ToString() + kvp.Value.ToString());
            }
        }

    }

Below is the part of the code where I have the deserialization.

                string message = null;
                bool gotMessage = false;
                while (Running)
                {
                    gotMessage = client.TryReceiveFrameString(out message); // this returns true if it's successful
                    if (gotMessage) break;
                }

                if (gotMessage)
                {
                    Debug.Log("Received " + message);
                    ParseReceivedData myParser = ParseReceivedData.CreateFromJSON(message);
                    myParser.PrintOutput();
                }

I attached the entire code file.

The error message is:
NullReferenceException: Object reference not set to an instance of an object

The error points to the PrintOutput() function call. Could you kindly help me understand what it is that I am doing wrong and how do I correct this?

Thank you!

6095013–662412–HelloRequester.cs (3.09 KB)

Switch to json.net, it should handle this much better.

Should your json not be:

{ player_dict : {"p1": "player1", "p2": "player2"} }

That said, Unity Json Utility doesn’t handle Dictionary I believe, unless that was added recently?

1 Like

I did not form the json but converted a python dict directly and hence the json string is such. Should it be as you advice?
I am following the unity example from this link https://docs.unity3d.com/2019.1/Documentation/ScriptReference/JsonUtility.FromJson.html

Well… First of all Unity’s JsonUtility is a pure object mapper. The important thing you have to understand that the JsonUtility can only map json objects to actual classes or structs. The members (key-value pairs) of that json object have to match the actual fields of the class / struct. Further more the JsonUtility has the same restrictions as the normal serialization system in Unity. So it doesn’t support serializing a dictionary at all. Another arbitrary limitation is that the root element has to be an object and can’t be an array (at least up to this date).
So if your json looks like this:

{"p1": "player1", "p2": "player2"}

the class that would match this object would look like this:

[System.Serializable]
public class Data
{
    public string p1;
    public string p2;
}

Of course you can’t have variable number of values this way since, as I said, the JsonUtility can only map to concrete objects / classes.

However instead of Unity’s JsonUtility you could use my SimpleJSON parser. My parser does not deserialize to custom objects but to specific classes which just represent the json data in an easy-to-manage data structure. With this parser you can simply do

var obj = JSON.Parse(jsonString);
foreach(var kvp in obj)
{
    Debug.Log("Dict = " + kvp.Key + " : " + kvp.Value.Value);
}

Note that while using dynamic key values in a json object is possible, it’s not really a great approach. If you have variable amount of members it’s better to use an array. If you need to group several properties together you usually use an array of ojects. Something like this:

[
{
"name":"player1",
"hp":100
},
{
"name":"player2",
"hp":75
}
]
5 Likes

Thank you so much! I followed what you described and it all worked beautifully. Great job with the SimpleJSON parser. :):slight_smile: