var result = JsonUtility.FromJson<(string,string)[]>("{}");
Debug.Log($"Type: {result.GetType()} IsArray: {result.GetType().IsArray} Length: {result.Length}");
In general I highly suggest staying away from Unity’s JSON “tiny lite” package. It’s really not very capable at all and will silently fail on very common data structures, such as bare arrays, tuples, Dictionaries and Hashes and ALL properties.
Instead grab Newtonsoft JSON .NET off the asset store for free, or else install it from the Unity Package Manager (Window → Package Manager).
Decided to test it on different very fresh project.
unity 2021.3.11
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestComponent : MonoBehaviour
{
[Serializable]
public class MyClass
{
}
void Start()
{
var result0 = JsonUtility.FromJson<MyClass[]>("{}");
Debug.Log($"Type: {result0.GetType()} IsArray: {result0.GetType().IsArray} Length: {result0.Length}");
var result = JsonUtility.FromJson<int[]>("{}");
Debug.Log($"Type: {result.GetType()} IsArray: {result.GetType().IsArray} Length: {result.Length}");
var result2 = JsonUtility.FromJson<MyClass[]>("{}");
Debug.Log($"Type: {result2.GetType()} IsArray: {result2.GetType().IsArray} Length: {result2.Length}");
}
}
Notice first and last are the same. (result0 and result 2)
But they have different Debug.Log
Only tried in Unity 2022.2 but there it was the middle result that would get the random lengths some of the time. The lengths also changes randomly, making it more plausible that it’s some uninitialized memory.
Note that JsonUtility doesn’t actually support arrays directly, you’d have to wrap them in a class to (de-)serialize them. Maybe it internally errors out at some point, leaving the returned object only half-initialized.
Unity 2021.3.15 is consistently alternating between result0 and result2 having an incorrect value. I passed the code to GPT-4 and it immediately made a comment about JsonUtility not handling arrays of empty objects correctly and suggested the following modification:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestComponent : MonoBehaviour
{
[Serializable]
public class MyClass
{
}
T[] SafeJsonArrayFromJson<T>(string json)
{
if (json == "{}")
{
return new T[0];
}
else
{
return JsonUtility.FromJson<T[]>(json);
}
}
void Start()
{
var result0 = SafeJsonArrayFromJson<MyClass>("{}");
Debug.Log($"Type: {result0.GetType()} IsArray: {result0.GetType().IsArray} Length: {result0.Length}");
var result = SafeJsonArrayFromJson<int>("{}");
Debug.Log($"Type: {result.GetType()} IsArray: {result.GetType().IsArray} Length: {result.Length}");
var result2 = SafeJsonArrayFromJson<MyClass>("{}");
Debug.Log($"Type: {result2.GetType()} IsArray: {result2.GetType().IsArray} Length: {result2.Length}");
}
}
Good for it to pick up the JsonUtility limitation but the solution is nonsense. This would be more appropriate:
public T SafeFromJson<T>(string json)
{
if (typeof(T).IsArray)
throw new Exception($"SafeFromJson: JsonUtility does not support arrays directly, wrap them in a class or struct first.");
return JsonUtility.FromJson<T>(json);
}