How to store a nullable int into a .json file?

I’m trying to store an ‘int?’ - a.k.a. Nullable - into a .json file, but until now I haven’t found any light on this. Could someone enlighten me, please?

I use the good 'n old System.IO to save to .json file format.

Thanks in advance.

This script works by representing a nullable integer as a JSON string value instead of the normal JSON integer or null values. To do this without access to the internal workings of the parser (e.g. UnityEngine.JSONUtility), I made an intermediary class which contained string fields instead of nullable fields, and then copied the values across to a class with nullable fields.

ExampleScript.cs

using UnityEngine;

public class ExampleScript : MonoBehaviour
{
	public class MyClassIntermediate
	{
		public int normalInt;
		public string nullableInt1;
		public string nullableInt2;

		// empty constructor
		public MyClassIntermediate() { }

		// from normal class
		public MyClassIntermediate(MyClass other)
		{
			this.normalInt = other.normalInt;
			this.nullableInt1 = JsonUtilityExtensions.NullableIntToJson(other.nullableInt1);
			this.nullableInt2 = JsonUtilityExtensions.NullableIntToJson(other.nullableInt2);
		}
	}

	public class MyClass
	{
		public int normalInt;
		public int? nullableInt1;
		public int? nullableInt2;

		// empty constructor
		public MyClass() { }

		// from intermediate class
		public MyClass(MyClassIntermediate other)
		{
			this.normalInt = other.normalInt;
			this.nullableInt1 = JsonUtilityExtensions.JsonToNullableInt(other.nullableInt1);
			this.nullableInt2 = JsonUtilityExtensions.JsonToNullableInt(other.nullableInt2);
		}
	}

	private void Awake()
	{
		string json;
		MyClassIntermediate intermediate;
		MyClass myClass;


		// SERIALIZATION

		myClass = new MyClass();
		myClass.normalInt = 1;
		myClass.nullableInt1 = -2;
		myClass.nullableInt2 = null;

		// do intermediary stuff to represent nullable types as strings.
		intermediate = new MyClassIntermediate(myClass);

		// serialize normally.
		json = JsonUtility.ToJson(intermediate);

		Debug.Log("Serialized json: " + json);


		// DESERIALIZATION

		// parse normally.
		intermediate = JsonUtility.FromJson<MyClassIntermediate>(json);

		// do intermediary stuff to get nullable types from strings.
		myClass = new MyClass(intermediate);

		Debug.Log("Deserialized Data:");
		// use the deserialized data.
		Debug.Log("normalInt: " + myClass.normalInt);
		Debug.Log("nullableInt1: " + (myClass.nullableInt1 == null ? "null" : myClass.nullableInt1.ToString()));
		Debug.Log("nullableInt2: " + (myClass.nullableInt2 == null ? "null" : myClass.nullableInt2.ToString()));
	}
}

public static class JsonUtilityExtensions
{
	// The json string to represent null values.
	public const string JsonNull = "null";

	// Serializes a nullable integer to a json string.
	public static string NullableIntToJson(int? nullable)
	{
		if (nullable.HasValue)
			return nullable.Value.ToString();
		else
			return JsonNull;
	}

	// Parses a json string containing an integer or null.
	public static int? JsonToNullableInt(string json)
	{
		if (json == JsonNull)
			return null;
		else
		{
			try
			{
				return int.Parse(json);
			}
			catch // error, was not an integer or null!
			{
				Debug.LogError("JSON parsing error: Expected nullable integer.");
				return null;
			}
		}
	}
}