Load Data from JSON Array with data structure constantly changing, How to implement dictionaries?

Hi,

I’m currently trying to load data from different JSON files and display it in the UI.

Let’s say I’ve got 15 buttons each linked with a loadfromJSON and a file attached to it, and a procedurally generated window (panel with texts) that will display the information showing in bold the name of the value and in italic the value itself once you click on a button.
Each JSON is an array of items.

I’ve written a reader with a wrapper etc to be able to read and display each data.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

[System.Serializable]
public class ObjDataSerializable
{
    public string json_featuretype;
    public string Name;
    public string unique_id;
}
/*
*  Wrapper class for the SerializableItem class (into a List<>).
*/
[System.Serializable]
public class SerializableItemWrapper
{
    public List<ObjDataSerializable> Items;
}

and my JSON Structure is like this:

[
        {
            "json_featuretype": "Data",
            "Name": "16_SF_tpg_balk:400x400:2526996",
            "unique_id": "3Qliei1WzDfBfhHXUG3F5O_25"
        },
        {
            "json_featuretype": "Data",
            "Name": "16_tpg_balk:400x400:2527074",
            "unique_id": "3Qliei1WzDfBfhHXUG3F4k_26"
        }
]

In this example it’s easy and currently working as the structure is the same between the two items in the JSON file. But in some cases, I won’t have the name, or I’ll get extra information.

Therefore I can’t work with this part as it should be generated based on the data from the JSON not from a predefined class.

[System.Serializable]
public class ObjDataSerializable
{
    public string json_featuretype;
    public string Name;
    public string unique_id;
}

The only var that will exist in all the items is the unique_id.
Should I write a reader that reads the JSON, parse the items in strings and generate the UI based on that ? Therefore I would forget about making them usable variables and keep them as strings.
How can I write an adaptable ObjDataSerializable ?

Thanks in advance for your help !

Boris

I’ve found that in cases like this, you’d be much better off using Dictionaries instead of structs or classes. The code is slightly more messy, but usually orders of magnitute more flexible.

I’ve found this example on the forum:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;// this namespace is required to import dictionaries
public class dictionaryExample : MonoBehaviour {
    public Dictionary<string, bool> myDictionary = new Dictionary<string, bool>();// declair key type and value type : <string, bool>
    public Dictionary<string, string> myDictionary2 = new Dictionary<string, string>();
    // Use this for initialization
    void Start () {
        if (myDictionary.Count < 10) {// gets count on dictionary
            string c = myDictionary.Count.ToString ();
            myDictionary.Add (c, false); // adds to dictionary
            myDictionary2.Add (c, c);
        }
        foreach (KeyValuePair<string, bool> i in myDictionary) { //you can use this  to return keys and values (key value pair)
            Debug.Log (i.Key);// i.Key will rwtun the key for that KVP
            Debug.Log(i.Value);// i.Value returns value fot the KVP
        }
        foreach (var i in myDictionary2) {// var can me used as a shortcut for many class types (in this case KeyValuePair <string, string>)
            Debug.Log (i.Key);
            Debug.Log(i.Value);
        }
        Debug.Log (myDictionary ["0"]);// this overload : myDictionary["0"]   will return the value associated to the Key : "0"
        if (myDictionary.ContainsKey ("9")) {
            myDictionary.Remove ("9"); // will remove a KVP
            Debug.Log ("Has Removed");
        }
        myDictionary2.Clear ();// will clear the dictionary
    }
}

I guess that I should write each item like this: KeyValuePair <string, string> then, that would be a lot easier indeed. Thanks a lot !

How should I cut out the item ? Write my how parser ? Any idea ?

From what I’ve tested, I need to split my Json Array each object being a dictionary of KeyValuePair.

So with a JSON like this:

[
        {
            "json_featuretype": "Data",
            "Name": "16_SF_tpg_balk:400x400:2526996",
            "unique_id": "3Qliei1WzDfBfhHXUG3F5O_25"
        },
        {
            "json_featuretype": "Data",
            "Name": "16_tpg_balk:400x400:2527074",
            "unique_id": "3Qliei1WzDfBfhHXUG3F4k_26",
            "Length": "400",
            "Width": "400"
        }
]

I should get two dictionaries like this:

Dictionary 1:

  • Key: “json_featuretype”, Value: “Data”
  • Key: “Name”, Value: “16_SF_tpg_balk:400x400:2526996”
  • Key: “unique_id”, Value: “3Qliei1WzDfBfhHXUG3F5O_25”

Dictionary 2:

  • Key: “json_featuretype”, Value: “Data”
  • Key: “Name”, Value: “16_tpg_balk:400x400:2527074”
  • Key: “unique_id”, Value: “3Qliei1WzDfBfhHXUG3F4k_26”
  • Key: “Length”, Value: “400”
  • Key: “Width”, Value: “400”

How should I setup my reader ? I don’t get it ? I’ve managed to split each object ( { 1 } & { 2 }) into a list of string, using a wrapper. It does find the correct amount of object but I can’t use them.

Here is my code :

    void LoadFromJSONFile(TextAsset jsonFileLoaded)
    {
        SerializableItemWrapper2 wrapper = new SerializableItemWrapper2();
        wrapper = JsonUtility.FromJson<SerializableItemWrapper2>(JsonCleaner(jsonFileLoaded));

        Debug.Log(" WRAPPER ITEM COUNT : " + wrapper.Items.Count); // I GET THE CORRECT COUNT

        for (int i = 0; i < wrapper.Items.Count; i++)
        {
            Debug.Log(wrapper.Items[i]); // DOESN'T DISPLAY ANYTHING. I CAN'T ACCESS THE STORED STRING
        }
    }

    /*
*  Wrapper class for the SerializableItem class (into a List<>).
*/
    [System.Serializable]
    public class SerializableItemWrapper2
    {
        public List<string> Items;
    }

For the fact that Unity can’t use top level arrays in JSON, I’m correcting it myself with the function JsonCleaner() when I’m loading the JSON file by including my JSON in { “Items”: [ JSON ] }.

Any idea on why my code doesn’t work ? How can I implement dictionaries instead of the List ? I need to convert/parse each string from my list into a new dictionary.

EDIT: I could play with an hashtable instead of a dictionary, but same problem I don’t get how to split first the array of object and then split each objects into a new hashtable/dictionary

Thanks in advance for your help !

Any reason you are not using a JSON library API? There are several, no need to reinvent the wheel.

That’s the files I’m continuously receiving and the app needs to manage (it’s not game related but more AEC).
I can ask if I could receive XML maybe, but there isn’t much they can do to manipulate the files prior sending them to me/unity. (the full workflow will be automated).
I’m using an editor script to extract the data from the different Json prior sending it with other information/gameobjects/scripts as assetbundles.

EDIT: Sorry, early morning, I’ve completely misread your post.
What would you recommend? I think I don’t have the knowledge yet on how the whole thing (Json libraries etc) works and how to write what I want. I know there are limitations to the JsonUtility from Unity, I read that it can’t handle top level arrays but it was on the roadmap (few years ago). I’m only starting to really understand the structure of the Json (in general, arrays, objects, key, value…).
Do you have any recommendation on which api to choose ? Odin Serializer ? What should I look for in terms of features to be able to do what I want.