Creating Json

Hi,

I’m trying to create a JSON, but I think I screwed up.
Each Level/Scene data is collected. The following Code shows how a JSON is created using the object of 1 Level:

public void CreateObject()
    {
        SaveObject saveObject = new SaveObject
        {
            data1 = dataArrayList[0].ToString(),
            data2 = dataArrayList[1].ToString(),
            data3 = dataArrayList[2].ToString(),
        };

        json = JsonUtility.ToJson(saveObject));

        data.Clear();
    }

    private class SaveObject
    {
        public string data1;
        public string data2;
        public string data3;
    }

The result:
{
“data1”:“nameOfData1”,
“data2”:“nameOfData2”,
“data3”:“nameOfData3”
}

But I want a JSON for the data of all levels. Just like this:

{
“Level1”:{
“data1”:“nameOfData1”,
“data2”:“nameOfData2”,
“data3”:“nameOfData3”
},
“Level2”:{
“data1”:“nameOfData1”,
“data2”:“nameOfData2”,
“data3”:“nameOfData3”
},
“Level3”:{
“data1”:“nameOfData1”,
“data2”:“nameOfData2”,
“data3”:“nameOfData3”
}
}

So I tried to save the objects of each Level/Scene in another ArrayList and create a JSON from an Object of Objects.

public void CreateJson()
    {
        JsonObject jsonObject = new JsonObject
        {
            Level0 = objectList[0].ToString(),
            Level1 = objectList[1].ToString(),
        };

        json = JsonUtility.ToJson(jsonObject);

        Debug.Log("The Json: " + json);
    }

    private class JsonObject
    {
        public string Level0;
        public string Level1;
    }

But the JSON I get then is totally abstruse (and not valid):

{
“Level0”:“{"data1":"nameOfData1","data2":"nameOfData2",
"data3":"nameOfData3"}”,
“Level1”:“{"data1":"nameOfData1","data2":"nameOfData2",
"data3":"nameOfData3"}”,
“Level2”:“{"data1":"nameOfData1","data2":"nameOfData2",
"data3":"nameOfData3"}”
}

I’m stuck. How can this result be and how can I fix it?

In Unity, you can not have list as top level object in json. You want this:

public class SaveObjectList {
    public SaveObject[] objects;
}

What @palex-nx says is right on but I’ll take it one step further: Stay away from Unity’s JSON… it may be performant but it is actually more-correctly described as “mini-ultra-super-lite-JSON” because it lacks the fundamental support one expects from a JSON implementation in 2019.

It’s really a shame Unity crippled their internal JSON the way they did. Use it at your own peril and expect to regularly find stuff it cannot do, like Dictionaries and Lists and other simple stuff that Should Just Work™.

I recommend getting NewtonSoft JSON for free from the asset store. It will do everything you need and more:

1 Like

Your main problem seems to be that you are converting your objects to strings, and then creating a JSON representation of the strings rather than a JSON representation of the original objects.

If you have a hierarchy of several nested objects, you should not convert the leaf objects into JSON and then put them into more objects, you should convert the entire hierarchy in one pass. Create a single object that contains all the data you want to serialize (as objects, not as strings) and then JSON-ify that top-level object.

I think the JSON you posted actually is completely valid JSON if you remove the line breaks, it’s just not the JSON you want: each level is a single string-type variable containing an (escaped) JSON description.

A more recent version of newtonsoft json for Unity which is AoT compliant:
https://github.com/jilleJr/Newtonsoft.Json-for-Unity

I use it for polymorphism in my projects. Super handy as Unity’s Json utility doesn’t support that.
The only thing I couldn’t really find is a method like JsonUtility.Overwrite which takes the already existing object and overwrites the values. JsonConvert.DeserializeObject always creates a new one.

I believe you may be looking for this function:

https://www.newtonsoft.com/json/help/html/PopulateObject.htm

It is indeed present in the asset store pack I linked above, but I didn’t look in the AOT git repo you linked.

Not to hijack this thread but the problem with PopulateObject is that it will keep adding items to a List rather than overwriting them even though it is set to re-use. It re-uses the List but not its items. The array would grow and grow with duplicate items when the class is deserialized multiple times over with a nearly identical json such as a manifest. It causes allocation everytime to deserialize instead of re-using the items in the list for less allocation.