- Home /
Issue assigning JSON Data to Class Structure
Hello there!
Here's a bit of background information:
I'm making a GET request to retrieve JSON data, and I'm trying to store that data into a structure of classes. Printing the retrieved data to the console works, but assigning it to the classes does not (it remains empty in the inspector after the request.)
I’ve split the code into two sections.
1. Makes the web request and attempts to store the data into a class structure.
2. The current class structure
Here is a link to the JSON Data I’m using.
public class WebRequestTest : MonoBehaviour
{
public string uri = "https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=5min&apikey=demo";
public RootObject rootObj;
void Start()
{
StartCoroutine(GetRequest(uri));
}
IEnumerator GetRequest(string uri)
{
UnityWebRequest req = UnityWebRequest.Get(uri);
yield return req.SendWebRequest();
Debug.Log(req.downloadHandler.text);
rootObj = JsonUtility.FromJson<RootObject>(req.downloadHandler.text);
}
}
Below is the structure for my classes so far. I'm imagining that the issue might be with TimeSeries.dataPeriods.
(TLDR: I wasn't sure whether to use an array, a list, or something else; but I settled on a list.)
[Serializable]
public class RootObject
{
public MetaData metaData;
public TimeSeries timeSeries;
}
[Serializable]
public class MetaData
{
public string Information;
public string Symbol;
public string LastRefreshed;
public string OutputSize;
public string TimeZone;
}
[Serializable]
public class TimeSeries
{
public List<DataPeriod> dataPeriods;
}
[Serializable]
public class DataPeriod
{
public Data data;
}
[Serializable]
public class Data
{
public string Open;
public string High;
public string Low;
public string Close;
public string Volume;
}
You may have noticed in the Data class that I stored all the numeric data as strings. I thought I'd need to store them this way at first because they are coming from JSON and then convert them later when needed. (Perhaps there is a more elegant way to handle this?)
Final questions:
1. Am I handling comma separated objects the right way by using a list or should I be doing something else?
2. Does anything stand out as to whats preventing the data from being assigned into the RootObject class?
3. If you have any insights about what would be a good way to handle converting the numbers to ints/floats when the class is created, I would love to hear it!
Thank you so much for reading this! I'm going to keep working on this and will post an update when I can.
Answer by Bunny83 · Apr 16, 2019 at 09:29 PM
The Json data that your server provides can't be mapped to a class since your keys contain illegal characters for C# classes. Specifically spaces, brackets, dashes and colons. Furthermore the data doesn't contain a single array (json array). The whole data is composed of objects. So you can not use Lists or arrays at all. Unity's JsonUtility is very limited. For arbitrary data you may want to use my SimpleJSON library.
It does not parse the data into actual C# classes but into generic nodes to represent objects as Dictionarys (JSONObject) and arrays as lists (JSONArray). Though the interface is designed to make the usage extremely easy. You almost never have to deal with the individual node types. There are many casting properties and implicit type conversions built into the JSONNode base class.
To use SimpleJSON, just place the file in your project and do:
var root = JSON.Parse(req.downloadHandler.text);
string info = root["Meta Data"]["1. Information"].Value;
var timeSeries = root["Time Series (5min)"];
foreach(var kv in timeSeries)
{
Debug.Log("Time: " + kv.Key);
Debug.Log("open: " + kv.Value["1. open"].Value);
}
Note that if you control the format of your json data i strongly recommend you change it. Using things like 1, 2, 3 combined with a text as key is extrem bad style.
Thank you for the amazing response! Your explanation really helped to clarify this topic and that is quite an amazing library you’ve made.
It took me a little while to get one of the string keys to log out correctly, mainly because of a silly 1 character typo haha.
Definitely makes me think you’d use constants for the keys ins$$anonymous$$d of typing them out. I didn’t have control over the data format but I can totally see how the numbers with text is a bad na$$anonymous$$g convention.
Again many thanks for the clarification on this though Bunny and for sharing your library!
Yes, I have already realised that this Web service you're using there is really an official one. They should win a price for one of the worst designed APIs. Json is mainly meant for computer processing. It seems they tried to make it more "human readable" and violates the basic principles of database normalization.
It's actually worse than I expected. The two examples (this and this) have actual different information fields. They always put those numbers before their keys, no matter which key it is. So while the key is "6. Time Zone"
in the first case, it's "5. Time Zone"
in the second ... (no words)
You may be better off using their CSV format which seems to be a lot cleaner. Even you have to parse the CSV format yourself it seems much more robust than their strange json format.
Haha yea, it's pretty strange decision they made going with that. I'll be sure to pass along your thoughts on it if I speak with them.
Even though I'm not going to go much further with this project (it was more of an experiment in data visualization,) I'm going to check out parsing their CSV format because I'm sure its important to understand how to do it in the long-term.
If you have any handy reference material on that I'm sure anyone reading this and I will greatly appreciate it!
Thanks again.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Parsing multiple json files that are referencing each other 0 Answers