Search Unity

JSONUtility One works and another similar isn't. What am I missing?

Discussion in 'Scripting' started by Seaworth, Sep 16, 2019.

  1. Seaworth

    Seaworth

    Joined:
    Aug 15, 2019
    Posts:
    19
    Hi folks,

    I have two lots of code which as far as I can see are similar, but only one works.

    Working code:

    Code (CSharp):
    1. //WheelyThings.cs
    2. [System.Serializable]
    3. public class WheelyThings
    4. {
    5.     // Start is called before the first frame update
    6.     public string Make;
    7.     public string Model;
    8.     public int Wheels;
    9. }
    10.  
    11.  
    12. //WheelyList.cs
    13.  
    14. using System.Collections.Generic;
    15. [System.Serializable]
    16. public class WheelyList
    17. {
    18.     public List<WheelyThings> Vehicles = new List<WheelyThings>();
    19. }
    20.  
    21. JSONExample.cs
    22.  
    23. using System.Collections.Generic;
    24. using UnityEngine;
    25.  
    26. public class JSONExample : MonoBehaviour
    27. {
    28.     public WheelyList VehicleList = new WheelyList();
    29.  
    30.    void Start()
    31.     {
    32.         TextAsset asset = Resources.Load("Vehicles") as TextAsset;
    33.  
    34.         if(asset != null)
    35.         {
    36.                         VehicleList = JsonUtility.FromJson<WheelyList>(asset.text);
    37.                        Debug.Log("Count of Vehicles: " + VehicleList.Vehicles.Count);
    38.                         foreach(WheelyThings vehicle in VehicleList.Vehicles)
    39.                         {
    40.                             print(vehicle.Make + " " + vehicle.Model + " " + vehicle.Wheels);
    41.             //                print(vehicle.Model);
    42.               //              print(vehicle.Wheels);
    43.                         }
    44.         }
    45.         else
    46.         {
    47.             print("asset is mull");
    48.         }
    49.     }
    50. }
    51.  
    52. //WheelyThings.JSON
    53.  
    54. {
    55.   "Vehicles": [
    56.     {
    57.       "Make": "Toyota",
    58.       "Model": "Camry",
    59.       "Wheels": 4
    60.     },
    61.     {
    62.       "Make": "Yamaha",
    63.       "Model": "YZF-R15",
    64.       "Wheels": 2
    65.     },
    66.     {
    67.       "Make": "Ford",
    68.       "Model": "Ranger",
    69.       "Wheels": 4
    70.     }
    71.   ]
    72. }
    73.  
    This code works. The count is three and the Vehicles are listed. However, the code below does not work:
    Code (CSharp):
    1. // Questions.cs
    2. using System.Collections.Generic;
    3.  
    4. [System.Serializable]
    5. public class Questions
    6. {
    7.     public int ID;
    8.     public string Category;
    9.     public string Question;
    10.     public int PointValue;
    11.     public string CorrAnswer;
    12.     public string altAnswer1;
    13.     public string altAnswer2;
    14.     public string altAnswer3;
    15. }
    16.  
    17. QuestionList.cs
    18.  
    19. using System.Collections;
    20. using System.Collections.Generic;
    21. using UnityEngine;
    22.  
    23. [System.Serializable]
    24. public class QuestionList {
    25.     public List<Questions> QuestionEntry = new List<Questions>();
    26. }
    27.  
    28. JSONExample.cs
    29. using System.Collections.Generic;
    30. using UnityEngine;
    31.  
    32. public class JSONExample : MonoBehaviour
    33. {
    34.     public QuestionList qList = new QuestionList();
    35.    void Start()
    36.     {
    37.         TextAsset asset = Resources.Load("QuizMaster") as TextAsset;
    38.  
    39.         if(asset != null)
    40.         {
    41.             qList = JsonUtility.FromJson<QuestionList>(asset.text);
    42.             Debug.Log("Count: " + qList.QuestionEntry.Count);
    43.             foreach(Questions questionq in qList.QuestionEntry)
    44.             {
    45.                 print(questionq.CorrAnswer);
    46.                 print("ooooooo");
    47.             }
    48.         }
    49.         else
    50.         {
    51.             print("asset is mull");
    52.         }
    53.     }
    54. }
    55.  
    56. // QuizMaster.json
    57.  
    58. {
    59.   "Questions" : [
    60.     {
    61.       "ID": "1",
    62.       "Category": "Chess",
    63.       "Question": "Who became world chess champion in 1948?",
    64.       "PointValue": 500,
    65.       "CorrAnswer": "Mikhail Botvinnik",
    66.       "altAnswer1": "Robert James Fischer",
    67.       "altAnswer2": "Samuel Reshevsky",
    68.       "altAnswer3": "Tigran Petrosian"
    69.     },
    70.     {
    71.       "ID": "2",
    72.       "Category": "Literature",
    73.       "Question": "Who was not one of the original Musketeers?",
    74.       "PointValue": 100,
    75.       "CorrAnswer": "D'artagnan",
    76.       "altAnswer1": "Athos",
    77.       "altAnswer2": "Porthos",
    78.       "altAnswer3": "Aramis"
    79.     },
    80.     {
    81.       "ID": "3",
    82.       "Category": "Literature",
    83.       "Question": "To begin with Marley was as dead as a doornail, are the opening lines to what novel?",
    84.       "PointValue": 200,
    85.       "CorrAnswer": "A Christmas Carol",
    86.       "altAnswer1": "The Turn of the Screw",
    87.       "altAnswer2": "The Scarlet Pimpernel",
    88.       "altAnswer3": "Howard's End"
    89.     }
    90.   ]
    91. }
    92.  
    The count is 0 and no listing is printed. What am I missing? Any help is much appreciated.
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    JsonUtility doesn't handle List or Dictionary. (I'm actually just surprised that your first example seems to work, it really shouldn't.) Use LitJson instead; similar operation, but much more capable.
     
    Seaworth likes this.
  3. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    "JsonUtility doesn't handle List or Dictionary"

    It does serialize list (just like Unity inspector will) if the list is contained in a serialized class, like in @Seaworth code. But it won't serialize dictionary, unless using ISerializationCallbackReceiver to circumvent dictionary limitation by putting keys and values into lists.
     
    Seaworth and Antypodish like this.
  4. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @Seaworth

    Your data has to be in very exact format for it to work - you need store a list inside serializable class, then serialize that class. Same goes for reading the json with JsonUtility... your data needs to be in format:

    Code (CSharp):
    1.  {
    2.   "questions":
    3.    [
    4.    ]
    5. }
    But now in your data, you have "Questions" when it should be the thing contained in container class. I changed the names a bit to make it more easy to understand (for myself mostly):

    Code (CSharp):
    1. public class JsonExample : MonoBehaviour
    2. {
    3.     public List<Question> questions;
    4.     public TextAsset asset;
    5.  
    6.     void Start()
    7.     {
    8.         if(asset != null)
    9.         {
    10.             // json format needed:  {"questions":[]}
    11.  
    12.             // Get questions container
    13.             var json = JsonUtility.FromJson<QuestionList>(asset.text);
    14.  
    15.             // Get questions list from container
    16.             questions = json.questions;
    17.         }
    18.     }
    19. }
    20.  
    21. // container for questions
    22. [System.Serializable]
    23. public class QuestionList
    24. {
    25.     public List<Question> questions = new List<Question>();
    26. }
    27.  
    28.  
    29. // question
    30. [System.Serializable]
    31. public class Question
    32. {
    33.     public int ID;
    34.     public string Category;
    35.     public string question;
    36.     public int PointValue;
    37.     public string CorrAnswer;
    38.     public string altAnswer1;
    39.     public string altAnswer2;
    40.     public string altAnswer3;
    41. }
    And your JSON has to be changed to match class contents, like I mentioned, for this to work:
    Code (CSharp):
    1. {
    2.     "questions": [
    3.         {
    4.             "ID": "1",
    5.             "Category": "Chess",
    6.             "Question": "Who became world chess champion in 1948?",
    7.             "PointValue": 500,
    8.             "CorrAnswer": "Mikhail Botvinnik",
    9.             "altAnswer1": "Robert James Fischer",
    10.             "altAnswer2": "Samuel Reshevsky",
    11.             "altAnswer3": "Tigran Petrosian"
    12.         },
    13.         {
    14.             "ID": "2",
    15.             "Category": "Literature",
    16.             "Question": "Who was not one of the original Musketeers?",
    17.             "PointValue": 100,
    18.             "CorrAnswer": "D'artagnan",
    19.             "altAnswer1": "Athos",
    20.             "altAnswer2": "Porthos",
    21.             "altAnswer3": "Aramis"
    22.         },
    23.         {
    24.             "ID": "3",
    25.             "Category": "Literature",
    26.             "Question": "To begin with Marley was as dead as a doornail, are the opening lines to what novel?",
    27.             "PointValue": 200,
    28.             "CorrAnswer": "A Christmas Carol",
    29.             "altAnswer1": "The Turn of the Screw",
    30.             "altAnswer2": "The Scarlet Pimpernel",
    31.             "altAnswer3": "Howard's End"
    32.         }
    33.     ]
    34. }
     
    Seaworth likes this.
  5. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    In your second example, your saved list in your json file is Questions where as the name in the class is QuestionEntry.

    Change "Questions" to "QuestionEntry" in the json or rename the list to Questions and it should work.
     
    Seaworth likes this.
  6. Seaworth

    Seaworth

    Joined:
    Aug 15, 2019
    Posts:
    19
    That seems to have worked. I changed QuestionEntry to Questions and voila. Now to check with the full JSON set. Thank you!!