De/Serializing Top Level Arrays in JSON with Unity.

Well it has been a while since my last tutorial. I’ve been experimenting with video tutorials and working on my game and also doing some paid project work at the same time. At least I am not bored!

That being said I like to note something down when I find something new or tricky that I get stuck on and today’s is simple but effective. For those that don’t know Unity actually has a nifty built in tool to serialize and de-serialize objects through the JsonUtility class. This is super useful for creating more human-readable data quickly and then adding it into your game. There is only one tiny problem for me, it doesn’t handle top level arrays. By that I mean the following won’t work.

[{"myvar";"myvalue"},{"myvar":"myothervalue"}]

I’m not sure the reasoning but my searches online did reveal from Unity staff that they currently do not support this feature. The easiest way to fix this is just wrap the array in a top level object like below.

{[{"myvar";"myvalue"},{"myvar":"myothervalue"}]}

It is a simple fix but it is annoying if you want to serialize or deserialize straight to (or from) an array, which is what I needed to do. So let’s look at making a JsonHelper class that fixes this issue for us by wrapping up top level arrays in a Wrapper class.

using System;

public static class JsonHelper {

    public static T[] FromJson<T>(string json) {
        Wrapper<T> wrapper = UnityEngine.JsonUtility.FromJson<Wrapper<T>>(json);
        return wrapper.Items;
    }

    public static string ToJson<T>(T[] array) {
        Wrapper<T> wrapper = new Wrapper<T>();
        wrapper.Items = array;
        return UnityEngine.JsonUtility.ToJson(wrapper);
    }

    [Serializable]
    private class Wrapper<T> {
        public T[] Items;
    }
}

The above code provides a simple black box to allow you to serialize or de-serialize those top level arrays but how does it work? The Wrapper is a [Serializable] class that is essentially empty, in fact it only holds a generic array. The generic array is for all intents and purposes our top level array. The thing we actually want to work with.

When de-serializing an array from Json it simply loads the Wrapper class, ignores the wrapper itself and returns the array. Conversely when serializing into Json we create a wrapper so that we have something to hold our array in. We then assign the array passed in to our function as the wrapper’s local variable. Lastly we use the built in JsonUtility to return the string back for writing.

There is now only one slight change to our Json file, the array is actually named therefore we should tweak it to suit. In any situations where you want to use a top level array instead  of using our first example instead wrap it in an object and label the array “Items” as shown below.

{"Items":[{"myvar";"myvalue"},{"myvar":"myothervalue"}]}

NOTE: This only applies if you are ever manually creating the json you want to de-serialize. If for some reason you’re only ever going to be loading objects you’ve previously saved the JsonUtility does this for you.

Easy? You bet, but that was the whole point!