2

I'm getting User IDs (int64) from JSON and then passing them into a function to populate user data. However the JSON ID value I get changes once I pass it through a iEnumerator function. Any idea why this happens?

I have printed the values and know for sure they are the expected JSON values before i pass them.

I am getting the IDs with GetTeachersStudentList and passing them into PopulateStudentGamesAndTutorial. The dictionaries I am using to store the IDs and data are initialized right before GetTeachersStudentList is called.

IEnumerator GetTeachersStudentList()
{
    //get user information from server call 
    Dictionary<string, string> headers = new Dictionary<string,string>();
    headers.Add("Access-Token", PlayerData.accessToken);
    string url = studentURL += "?staffId=" + PlayerData.currentUser.staffId;

    WWW www = new WWW(url, null, headers);

    yield return www;

    StudentListWebResponse = www.text;
    PlayerData.studentList = StudentListWebResponse; 

    //parse json
    JSONArray students = (JSONArray) JSON.Parse(StudentListWebResponse);
    expectedStudentsToPopulate = students.Count;

    //populate each users data 
    for (int i = 0; i < students.Count; i++)
    {
        string userInformation = students[i].ToString();
        JSONObject studentJsonObject = (JSONObject) JSON.Parse(userInformation);
        foreach (var item in studentJsonObject)
        {
            //look for id, then use that id to populate user data
            if (item.Key == "id")
            {
                StartCoroutine(PopulateStudentGamesAndTutorial(item.Value));
            }
        }
    }

    PlayerData.control.Save();
}

IEnumerator PopulateStudentGamesAndTutorial(Int64 id)
{
    //get games with id 
    Dictionary<string, string> headers = new Dictionary<string,string>();
    headers.Add("Access-Token", PlayerData.accessToken);

    string studentGameURL = serverManager.GamesURL(id);
    WWW gamesWWW = new WWW(studentGameURL, null, headers);
    yield return gamesWWW;  
    PlayerData.StudentListWithGames.Add(id, gamesWWW.text);

    //get tutorials with id 
    string tutorialURL = serverManager.TutorialURL(id);
    WWW wwwGetTutorialsCompleted = new WWW(tutorialURL, null, headers);
    yield return wwwGetTutorialsCompleted;
    JSONArray tutorialArray = (JSONArray) JSON.Parse(wwwGetTutorialsCompleted.text);
    List<int> tutorialIDList = new List<int>();
    for (int i = 0; i < tutorialArray.Count; i++)
    {
        tutorialIDList.Add(tutorialArray[i]["id"]); 
    }
    PlayerData.StudentListWithTutorials.Add(id, tutorialIDList);
    PlayerData.control.Save();
Ben
  • 34,935
  • 6
  • 74
  • 113
Blair
  • 43
  • 1
  • 4
  • You've no reason to expect Json to support Int64 numbers. You need to define this field as a string for the purposes of serialisation. You can probably do this with an attribute, depending on what Json lib you are using. – Ben Dec 18 '18 at 16:55
  • 1
    possible dupe : [What is the accepted way to send 64-bit values over JSON?](https://stackoverflow.com/q/209869/327083) – J... Dec 18 '18 at 16:58
  • Where did they have the expected value and where does it differ? I can see that you're passing the ID around to many places, are all of them declared as `Int64`? – fredrik Dec 18 '18 at 16:58
  • related : https://stackoverflow.com/q/25839498/327083 – J... Dec 18 '18 at 16:58
  • If it adds anything, the number it changes to is always the same. An example of the expected id is 2586389028467909835. It always changes to -2147483648 regardless of the initial value. – Blair Dec 18 '18 at 16:59
  • 1
    What json library are you using? – Ben Dec 18 '18 at 16:59
  • 1
    If you're talking about uint64 and not int64 (ie : larger than `long.MaxValue`) : https://stackoverflow.com/q/9355091/327083 – J... Dec 18 '18 at 17:00
  • @ben Im using SimpleJSON – Blair Dec 18 '18 at 17:04
  • @blair that looks like one of the functions you're calling takes a signed and what you have is an unsigned, resulting in a overflow - provided that the library parsed it as an unsigned int64 of course. – fredrik Dec 18 '18 at 17:05
  • SimpleJSON node doesn't have an `operator Int64`. You need to use `AsString` together with `Int64.Parse` – Ben Dec 18 '18 at 17:11
  • @fredrik The value is unchanged right until i pass it into the PopulateStudentGamesAndTutorial function. Since its derives from JSON it is kept in a Dictionary, then im using the value from the dictionary to pass into the function. – Blair Dec 18 '18 at 17:13
  • @Ben @ fredrik Oh I see, alright ill give it a try! Im new to JSON and working with servers in general so you guys have been a big help! – Blair Dec 18 '18 at 17:15
  • @Blair haha I mean `Value` not `AsString`. – Ben Dec 18 '18 at 17:17
  • @Ben Worked! Thank you so much! And thanks to everyone else who helped. – Blair Dec 18 '18 at 17:23

1 Answers1

3

SimpleJSON stores all simple scalar values (such as Booleans, numbers and strings) as string. It provides accessor properties and operators to allow you to extract the value as a number of different types.

So for example:

bool b1 = node.AsBool; 
bool b1 = node; // Calls operator bool which in turn calls AsBool

This means that in most cases you can simply use the node as if it was already the correct type.

However there is no automatic conversion to Int64. If you try to use a node where an int64 is expected, the best match will be operator int which will not do what you want.

The solution is to pass it as a string, and use Int64.Parse or Int64.TryParse to convert it to the correct type.

Ben
  • 34,935
  • 6
  • 74
  • 113