Need to JSON serialize object with polymorphism

Can someone point me to the correct package and instructions on how to do this?

For something so simple why is there a hundred different paid/unpaid options out there? Been trying to do this for two days now. :sob:

And why the heck can’t unity get this to work in their implementation? This seems like a mandatory feature.

1 Like

This shouldn’t take you days.

Unity has supported polymorphic serialization since 2019. Fields serialized with [SerializeReference] will serialize with polymorphism, and will work when serialized with JsonUtility as well.

Example, using Odin Inspector for drawer support and buttons:

public class TestUnitySerializationComponent : MonoBehaviour
{
	#region Inspector Fields

	[SerializeReference]
	private BaseClass _baseClass;

	#endregion

	#region Unity Callbacks

	[Button("Json Utility", ButtonSizes.Medium)]
	public void SerializeWithJsonUtility()
	{
		var json = JsonUtility.ToJson(_baseClass, true);
		string path = GetFilePath();
		File.WriteAllText(path, json);
	}

	private static string GetFilePath()
	{
		return Application.persistentDataPath + "/Test.txt";
	}

	#endregion

	#region Nested Types

	public abstract class BaseClass
	{
		public int SomeInt;

		[SerializeReference]
		private NestedBaseClass _nestedClass;

		public class NestedBaseClass
		{
			public int NestedInt;
		}
	}

	public class DerivedClass : BaseClass
	{
		public float SomeFloat;

		public class DerivedNestedClass : NestedBaseClass
		{
			public float NestedFloat;
		}
	}

	#endregion
}

Json Utility Output:

{
    "SomeInt": 20,
    "_nestedClass": {
        "rid": 1000
    },
    "SomeFloat": 205.5,
    "references": {
        "version": 2,
        "RefIds": [
            {
                "rid": 1000,
                "type": {
                    "class": "TestUnitySerializationComponent/BaseClass/NestedBaseClass",
                    "ns": "LBG.Core.Testing",
                    "asm": "LBG-Core-Testing"
                },
                "data": {
                    "NestedInt": 0
                }
            }
        ]
    }
}

The Newtonsoft.Json package also supports polymorphism with the correct context settings. Not sure about Unity’s new serialization package. Then other serialization packages like the Odin Serializer support by-reference serialization by default, so no extra work is required.

2 Likes

omg… can’t believe it was that easy. I guess there was so much old info out there I kept going down bad rabbit holes.

Thx spiney199, i’ma go get drunk now. :face_with_symbols_over_mouth:

EDIT: for other people who want to do this then here is some code. no packages required.

[Serializable]
public class Object {
    public int ID;
}

[Serializable]
public class Child : Object {
    public int ID;
    public string name;
}

[Serializable]
public class Savefile {
    [SerializeReference] public List<Object> savables;
}

public class Manager 
{
    public Savefile savefile;

    public void Save() {
        string folder = Application.streamingAssetsPath + "/Savefile/";
        File.WriteAllText(folder + "savefile.json", JsonUtility.ToJson(savefile));
    }

    public void Load() {
        string folder = Application.streamingAssetsPath + "/Savefile/";
        savefile = JsonUtility.FromJson<Savefile>(File.ReadAllText(folder + "/savefile.json"));
    }
}

Uh, the list of Object needs to be decorated with [SerializeReference] not [SerializeField], otherwise you won’t get the by-reference serialization. That was kind of the single most important part of my post.

1 Like

Woops, updated.

1 Like