I'm trying to use Json to hold game dialog in a text asset file. I've tried to make a barebones project to test this and it is failing with the Error Message: ArgumentException: JSON must represent an object type.
I have a class called LineData which has a few properties each line of dialog contains. In the Json there are just two lines for now. When I import and parse it to try and make a reference to one of the lines of dialog it fails.
Here is all the code:
dialogJson.JSON:
[
{
"lineID": "BEDROOM_DAVE_0001",
"lineDialog": "Yaawwn, up i get for another fun packed day.",
"lineDuration": 3
},
{
"lineID": "BEDROOM_DAVE_0002",
"lineDialog": "Well I think I need a cigarette before I get to work!",
"lineDuration": 3
}
]
LineData.cs
using System;
[Serializable]
public class LineData
{
public string lineID;
public string lineDialog;
public float lineDuration;
}
GameController.cs
using UnityEngine;
public class GameController : MonoBehaviour
{
TextAsset Dialog_Data;
private void Start()
{
Dialog_Data = Resources.Load("txt/dialogJson");
LineData line1 = JsonUtility.FromJson(Dialog_Data.text);
Debug.Log("line 1 dialog = " + line1.lineDialog);
}
}
NOTE: I read here (https://answers.unity.com/questions/1503047/json-must-represent-an-object-type.html) that Unity "can't parse if the json consists of an array of objects". But I don't understand his explanation on how to get around this. Thanks
EDIT: I now have it without error, but the debug message is just empty didnt seem to get any data) . Here is the json now after the edits:
{ "LineData":
[
{
"lineID": "BEDROOM_DAVE_0001",
"lineDialog": "Yaawwn, up i get for another fun packed day.",
"lineDuration": 3
},
{
"lineID": "BEDROOM_DAVE_0002",
"lineDialog": "Well I think I need a cigarette before I get to work!",
"lineDuration": 3
}
]
}
I've also altered the GameController.cs like this (but now it says Index is outside array bounds:
public class GameController : MonoBehaviour
{
TextAsset Dialog_Data;
private void Start()
{
LineData[] lines = new LineData[2];
Dialog_Data = Resources.Load("txt/dialogJson");
lines = JsonUtility.FromJson(Dialog_Data.text);
Debug.Log("line 1 dialog = " + lines[0].lineDialog);
}
}
Answer
When you write a line like this:
LineData line1 = JsonUtility.FromJson(Dialog_Data.text);
You're saying "the JSON in this text string represents exactly one instance of the type LineData
". ie. the program is expecting something like this:
{
"lineID": "BEDROOM_DAVE_0001",
"lineDialog": "Yaawwn, up i get for another fun packed day.",
"lineDuration": 3
}
That's everything it needs to be able to populate exactly one LineData
object.
When instead you give it JSON like this:
[
{
"lineID": "BEDROOM_DAVE_0001",
"lineDialog": "Yaawwn, up i get for another fun packed day.",
"lineDuration": 3
},
{
"lineID": "BEDROOM_DAVE_0002",
"lineDialog": "Well I think I need a cigarette before I get to work!",
"lineDuration": 3
}
]
Then you're breaking your promise to the program that you were going to give it exactly one instance of type LineData
. Instead you've given it two instances packed into an array of type LineData[]
. In the eyes of a CPU, this is as different as being handed a chocolate bar to eat versus having a shipping container full of chocolate bars dropped on your foot. ;)
So, we need to tell the program to expect a shipping container. First, by defining what a shipping container full of LineData
looks like:
[Serializable]
public class LineDataCollection {
public LineData[] lines;
}
Then formatting our JSON to match this definition (one member named "lines" that holds an array of LineData objects):
{
"lines": [
{ /* Your first line data goes here */ },
{ /* Your second line data goes here... */ }
]
}
Then we need to tell our code to unpack a shipping container worth from the text, instead of just one LineData
:
LineDataCollection allLines = JsonUtility.FromJson(Dialog_Data.text);
// Select the first line from the collection, and print its dialogue:
Debug.Log("line 1 dialog = " + allLines.lines[0].lineDialog);
No comments:
Post a Comment