- Home /
JsonUtility array not supported?
I'm reading the documentation on JsonUtility.FromJson and find it hard to believe, that I can't serialize or deserialize an array of serializable objects. This works fine with plugins like LitJson, I was using before, so now I thought it was great, that Unity has json support built-in. Am I doing something wrong or is this maybe a feature to come in the future?
// Create some already tested dummy data.
User user = new User();
user.DisplayName = "TestName";
// Works fine with single object
string json = JsonUtility.ToJson(user);
Debug.Log(json); // returns valid json string.
Debug.Log(JsonUtility.FromJson<User>(json)); // works as it should.
// Doesn't work in array.
User[] usersArray = new User[3] {user,user,user};
string json2 = JsonUtility.ToJson(usersArray);
Debug.Log(json2); // returns "{}"
Debug.Log(JsonUtility.FromJson<User>(json2)); // is empty.
Thanks! :)
Answer by superpig · Jan 12, 2016 at 02:53 PM
Serializing/deserializing arrays and lists as top-level elements is not supported right now. It's on the to-do list...
Note that you can work around it in two ways for now:
Use ToJson() for each element in the array separately, and just stitch them together with "[", "," and "]"
Wrap the array in a structure like this:
[Serializable] public struct MyObjectArrayWrapper { public MyObject[] objects; }
Answer by JanouschScanblue · Jul 12, 2017 at 04:11 PM
Here is my implementation of a JsonUtility wrapper for arrays and lists and also nested arrays and lists.
void ParseJsonToObject(string json)
{
var wrappedjsonArray = JsonUtility.FromJson<MyWrapper>(json);
}
[Serializable]
private class MyWrapper
{
public List<MyObject> objects;
}
[Serializable]
private class MyObject
{
public int variable1;
public string variable2;
public List<MyNestedObject> nestedObjects;
}
[Serializable]
private class MyNestedObject
{
public string nestedVariable1;
public string nestedVariable2;
}
And the json would look like this
{ "objects": [
{
"variable1": "abc123",
"variable2": "def456",
"variable3": [
{
"nestedVariable1": "ghi789",
"nestedVariable2": "jkl101"
},
{
"nestedVariable1": "zxy789",
"nestedVariable2": "wfg101"
}
]
},
{
"variable1": "3qaghh5",
"variable2": "34qhah",
"variable3": [
{
"nestedVariable1": "3qwe54hb",
"nestedVariable2": "4ahb4e"
},
{
"nestedVariable1": "gverazh4",
"nestedVariable2": "233ghs"
}
]
}
] }
Unity 2017.2, still no array support. Took me a while but found your answer and it's by far the best solution in my opinion. Thanks alot!
Works great! I made the mistake of keeping my own nested structures as ScriptableObjects, which was why I was getting instance id's in my JSON. I removed ": ScriptableObject" from my class header and your approach worked perfectly!
Note that according to my tests, this does not support polymorphism for $$anonymous$$yObject
. So if you make a List<$$anonymous$$yObject>
, it will only serialize fields declared in $$anonymous$$yObject
, but not any child classes it may have; or none at all if $$anonymous$$yObject
is abstract.
Answer by matchsun · Mar 20, 2017 at 02:20 PM
a simple wrapper to support array
public JsonHelper ()
{
}
//Usage:
//YouObject[] objects = JsonHelper.getJsonArray<YouObject> (jsonString);
public static T[] getJsonArray<T>(string json)
{
string newJson = "{ \"array\": " + json + "}";
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>> (newJson);
return wrapper.array;
}
//Usage:
//string jsonString = JsonHelper.arrayToJson<YouObject>(objects);
public static string arrayToJson<T>(T[] array)
{
Wrapper<T> wrapper = new Wrapper<T> ();
wrapper.array = array;
return JsonUtility.ToJson (wrapper);
}
[Serializable]
private class Wrapper<T>
{
public T[] array;
}
}
Reworking the code snippet a bit to get it to compile, but works perfectly. Also works with generic List objects by using ToArray.
public class JsonHelper
{
//Usage:
//YouObject[] objects = JsonHelper.getJsonArray<YouObject> (jsonString);
public static T[] getJsonArray<T>(string json)
{
string newJson = "{ \"array\": " + json + "}";
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(newJson);
return wrapper.array;
}
//Usage:
//string jsonString = JsonHelper.arrayToJson<YouObject>(objects);
public static string arrayToJson<T>(T[] array)
{
Wrapper<T> wrapper = new Wrapper<T>();
wrapper.array = array;
return JsonUtility.ToJson(wrapper);
}
[System.Serializable]
private class Wrapper<T>
{
public T[] array;
}
}
string newJson = "{ \"array\": " + json + "}";
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(newJson);
Should be simply
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
Correct?
Yes, at least to make the two methods the exact opposite of each other. Currently "getJsonArray" expects a json string that only contains an array as top most element and it wraps it in the additional wrapper to be able to parse it. However "arrayToJson" does not remove the additional wrapper "text" from the converted JSON.
So a json string like "[1,2,3]"
would come out as an new int[]{1, 2, 3}
but "arrayToJson" would produce this from the same array: "{ "array": [1, 2, 3]}"
and not [1, 2, 3]
.
So you suggest that "getJsonArray" should be modified so it only accepts json in the form { "array": [ .... ]}"
. Though the better solution would be to actually remove the wrapper object and extract only the array JSON from the returned text. The point of this was to have a transparent "wrapper framework". So it was ment to allow direct conversion of a JSON array to an array and vice versa.
edit
Something like this:
public static T[] getJsonArray<T>(string json)
{
string newJson = "{ \"array\": " + json + "}";
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(newJson);
return wrapper.array;
}
public static string arrayToJson<T>(T[] array)
{
Wrapper<T> wrapper = new Wrapper<T> { array = array };
string json = JsonUtility.ToJson(wrapper);
var pos = json.IndexOf(":");
json = json.Substring(pos+1); // cut away "{ \"array\":"
pos = json.LastIndexOf('}');
json = json.Substring(0, pos-1); // cut away "}" at the end
return json;
}
So this will actually return a JSON array
string json = JsonHelper.arrayToJson(new int[]{1, 2, 3, 42});
// --> "[1, 2, 3, 42]"
// and the reverse:
int[] numbers = JsonHelper.getJsonArray(json);
Answer by Pablomon · Feb 01, 2021 at 03:35 PM
It is now the future, year 2021, a big pandemic has striken the whole planet. And seems like we still can't serialize Arrays as top-level elements without a wrapper. Has this issue been forgotten completely or I am missing something?
Answer by flashmandv · Jul 03, 2016 at 09:11 PM
I just tested it in Unity 5.3.5 declaring the field like this:
public Obbj[] obbs = new Obbj[] { new Obbj(), new Obbj() };
And it works :) It seems they added the array support
using 5.4, and i cant seem to get this to work all it outputs is this:
{}
did they remove it? or am i using it wrong?
you are probably using setters and getters.
refer to this link http://stackoverflow.com/questions/34274209/why-i-got-empty-json-string-returned-while-using-setter-and-getter-in-the-object