Search code examples
c#arraysjsonfastjson

How use fastJSON with a JSON array


I am using fastJSON to read data from a JSON file that I made, (the JSON file have data of a game's levels for a project in Unity, but that is not important). This is the JSON content:

{"1": {
    "background": "background1.png",
    "description": "A description of this level",
    "enemies": 
              [{"name": "enemy1", "number": "5"},
               {"name": "enemy2", "number": "2"}]},
 "2": {
    "background": "background1.png",
    "description": "A description of this level",
    "enemies": 
              [{"name": "enemy1", "number": "8"},
               {"name": "enemy2", "number": "3"}]},
"3": {
    "background": "background2.png",
    "description": "A description of this level",
    "enemies": 
              [{"name": "enemy2", "number": "5"},
               {"name": "enemy3", "number": "3"},
               {"name": "enemy4", "number": "1"}]}
}

This is my code:

using UnityEngine;
using System.Collections.Generic;
using fastJSON;

public class LevelManager : MonoBehaviour {

    private Dictionary<string, object> currentLevelData;

    public TextAsset levelJSON;
    public int currentLevel;

    // Use this for initialization
    void Start () {

        currentLevelData = LevelElements (currentLevel);
        if (currentLevelData != null) {
            Debug.Log (currentLevelData["background"]);
            Debug.Log (currentLevelData["description"]);
            /* How iterate the "enemies" array */
        } else {
            Debug.Log ("Could not find level '" + currentLevel + "' data");
        }
    }

    Dictionary<string, object> LevelElements (int level) {
        string jsonText = levelJSON.ToString();
        Dictionary<string, object> dictionary = fastJSON.JSON.Parse(jsonText) as Dictionary<string, object>;

        Dictionary<string, object> levelData = null;
        if (dictionary.ContainsKey (level.ToString ())) {
            levelData = dictionary [level.ToString ()] as Dictionary<string, object>;
        }

        return levelData;
    }
}

I don't know how iterate the array data with the name "enemies".


Solution

  • With the way your code is currently written, you would iterate over the enemies like this:

    foreach (Dictionary<string, object> enemy in (List<object>)currentLevelData["enemies"])
    {
        Debug.Log(enemy["name"]);
        Debug.Log(enemy["number"]);
    }
    

    However, I would recommend making some strongly typed classes to receive your data:

    public class Level
    {
        public string background { get; set; }
        public string description { get; set; }
        public List<Enemy> enemies { get; set; }
    }
    
    public class Enemy
    {
        public string name { get; set; }
        public string number { get; set; }
    }
    

    Ideally, this would allow you to deserialize like this:

    Dictionary<string, Level> dictionary = 
                              fastJSON.JSON.ToObject<Dictionary<string, Level>>(jsonText);
    

    Unfortunately, it seems that fastJSON cannot handle this (I tried it and got an exception). However, if you switch to a more robust library like Json.Net, it works with no problem:

    Dictionary<string, Level> dictionary = 
                            JsonConvert.DeserializeObject<Dictionary<string, Level>>(jsonText);
    

    This would allow you to rewrite your code so you can work with your data more more easily:

    public class LevelManager : MonoBehaviour
    {
        private Level currentLevelData;
    
        public string levelJSON;
        public int currentLevel;
    
        // Use this for initialization
        void Start()
        {
            currentLevelData = LevelElements(currentLevel);
            if (currentLevelData != null)
            {
                Debug.Log(currentLevelData.background);
                Debug.Log(currentLevelData.description);
    
                foreach (Enemy enemy in currentLevelData.enemies)
                {
                    Debug.Log(enemy.name);
                    Debug.Log(enemy.number);
                }
            }
            else
            {
                Debug.Log("Could not find level '" + currentLevel + "' data");
            }
        }
    
        Level LevelElements(int level)
        {
            string jsonText = levelJSON.ToString();
            Dictionary<string, Level> dictionary = 
                    JsonConvert.DeserializeObject<Dictionary<string, Level>>(jsonText);
    
            Level levelData = null;
            if (dictionary.ContainsKey(level.ToString()))
            {
                levelData = dictionary[level.ToString()];
            }
    
            return levelData;
        }
    }