question

Jose Pablo Monge Chacon avatar image
Jose Pablo Monge Chacon asked

Updating PlayFabSDK Serialization Issues

Hello! So silly me decided to try to update the PlayFab SDK in advance of our launch (by the end of the month). But apparently this was a very stupid mistake.

 

Pretty much all of the functions that are related to cloud script just suddenly stopped working. For example:

 

    void GetInfoFromIDCallback (RunCloudScriptResult result)
    {
        //Debug.Log(result.ResultsEncoded);
        JsonObject values = (JsonObject)result.Results;
        object container;
        values.TryGetValue("messageValue", out container);

        string faceID = "";
        if (result.ResultsEncoded.Contains("FacebookInfo"))
        {
            faceID = ((UserAccountInfo)container).FacebookInfo.FacebookId;
           // faceID = values["messageValue"]["UserInfo"]["FacebookInfo"]["FacebookId"].ToString();
        }

.

.

.

 

This used to work very simply by just adding these 2 lines

Dictionary<string, JToken> values = JsonConvert.DeserializeObject<Dictionary<string, JToken>>(result.Results.ToString());

 

faceID = values["messageValue"]["UserInfo"]["FacebookInfo"]["FacebookId"].ToString();

 

The cloudscript result, just holds the AccountInfo that was request in the server.

I thought with serialization would be easier to cast object from the Client Models than before so I should be able to just cast it as it is. But heres the error:

InvalidCastException: Cannot cast from source type to destination type.

 

I have tried this:

       string jsonData = PlayFab.SimpleJson.SerializeObject(container);
       UserAccountInfo account = PlayFab.SimpleJson.DeserializeObject<UserAccountInfo>(jsonData);

 

but it just creates a UserAccountInfo with null values.

 

Right now, am clueless, and I have no idea what I should. Anyone can give me a hand?? Why was this change so big?? (I tried changing to ExecuteCloudScript, but decided not too since nothing is working at all right now).

A little frustrated... thanks in advance.

 

 

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

We have a blog post we'll be publishing next week which goes into more detail on the change to JSON serialization in the Unity SDK, but the short version is that we couldn't continue to use JSON.net, so we evaluated the existing serializers and chose to use SimpleJson as the basis for our new code. If you want to make the move to the new SDK, the way to update your deserialization code is to update like so:

PlayFab.SimpleJson.DeserializeObject<[SomeType]>([string of JSON], Util.ApiSerializerStrategy);

You'll still be able to use JSON.net if you prefer it, as well. We created a wrapper layer (ISeralizer) which you can use to wrap any other JSON deserializer, and we have an example package specifically for JSON.net.

Finally though, if you are updating I would recommend moving to the newer ExecuteCloudScript. It has better debugging, including providing more info through the game manager on script execution (as well as being simpler to use).

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Jose Pablo Monge Chacon avatar image
Jose Pablo Monge Chacon answered

Oh BTW the only way I was able to get SOMETHING working, went from this:

 

     jsonKeys = JsonConvert.DeserializeObject<Dictionary<string, JToken>>(result.Results.ToString());

            playerInfo.genre = jsonKeys["messageValue"]["Genre"]["Value"].ToString();
            playerInfo.currBodyItem = jsonKeys["messageValue"]["CurrBodyItem"]["Value"].ToString();
            playerInfo.currHeadItem = jsonKeys["messageValue"]["CurrHeadItem"]["Value"].ToString();
            playerInfo.currCharacterSet = jsonKeys["messageValue"]["CurrTexture"]["Value"].ToString();
            playerInfo.playerLevel = jsonKeys["messageValue"]["PlayerLevel"]["Value"].ToString();
            playerInfo.currEXP = int.Parse(jsonKeys["messageValue"]["CurrentExperience"]["Value"].ToString());

 

to this

jsonKeys = (JsonObject)result.Results;
            object objectContainer;

            jsonKeys.TryGetValue("messageValue", out objectContainer);
            object value;
            ((JsonObject)objectContainer).TryGetValue("Genre", out value);
            object actualData;

            playerInfo.genre = (string)actualData;

            ((JsonObject)objectContainer).TryGetValue("CurrBodyItem", out value);
            ((JsonObject)value).TryGetValue("Value", out actualData);
            playerInfo.currBodyItem = (string)actualData;

            ((JsonObject)objectContainer).TryGetValue("CurrHeadItem", out value);
            ((JsonObject)value).TryGetValue("Value", out actualData);
            playerInfo.currHeadItem = (string)actualData;

            ((JsonObject)objectContainer).TryGetValue("CurrTexture", out value);
            ((JsonObject)value).TryGetValue("Value", out actualData);
            playerInfo.currCharacterSet = (string)actualData;

            ((JsonObject)objectContainer).TryGetValue("PlayerLevel", out value);
            ((JsonObject)value).TryGetValue("Value", out actualData);
            playerInfo.playerLevel = (string)actualData;

            ((JsonObject)objectContainer).TryGetValue("CurrentExperience", out value);
            ((JsonObject)value).TryGetValue("Value", out actualData);
            playerInfo.currEXP = int.Parse((string)actualData);

 

Which I hope you will agree became a little ridiculous....

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Jose Pablo Monge Chacon avatar image
Jose Pablo Monge Chacon answered

Very well, that helped!!

Now am facing a problem... again with the serializing:

 

        JsonObject values = (JsonObject)result.Results;
        object container;
        values.TryGetValue("messageValue", out container);

        string jsonData = PlayFab.SimpleJson.SerializeObject((JsonObject)container);
        UserAccountInfo account = new UserAccountInfo();
        account = PlayFab.SimpleJson.DeserializeObject<UserAccountInfo>(jsonData, Util.ApiSerializerStrategy);

This line always makes the account  information be null, even though the jsonData is correct... weird here is that this actually works:

 

            jsonKeys = (JsonObject)result.Results;
            object objectContainer;
            jsonKeys.TryGetValue("messageValue", out objectContainer);

            string jsonData = PlayFab.SimpleJson.SerializeObject((JsonObject)objectContainer);
            Dictionary<string, UserDataRecord> data = new Dictionary<string, UserDataRecord>();
            data = PlayFab.SimpleJson.DeserializeObject<Dictionary<string,UserDataRecord>>(jsonData, Util.ApiSerializerStrategy);

            playerInfo.genre = data["Genre"].Value;
            playerInfo.currBodyItem = data["CurrBodyItem"].Value;
            playerInfo.currHeadItem = data["CurrHeadItem"].Value;
            playerInfo.currCharacterSet = data["CurrTexture"].Value;
            playerInfo.playerLevel = data["PlayerLevel"].Value;
            playerInfo.currEXP = int.Parse(data["CurrentExperience"].Value);

 

Any idea why this might not be working??

 

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

I don't quite follow what you're attempting to deserialize. Is this the results coming from a script, or a call to one of the Get... API methods? The top part is trying to retrieve the user record you'd get from GetAccountInfo, while the bottom is trying to get info from user data of some sort, so I'm guessing this is likely trying to deserialize the info coming from the script. Can you let us know the Title ID for the script and the revision number?

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Jose Pablo Monge Chacon avatar image
Jose Pablo Monge Chacon answered

Sure thing:

BD4D Title ID

Revision 262

 

But the function is very simple:

handlers.getUserInfoWithID = function (args)
{
    var getInfo = server.GetUserAccountInfo({
        PlayFabId : args.PlayerID
    });
    
    log.debug(getInfo);
    log.debug(getInfo.data);
    
    return { messageValue : getInfo };
}

Pretty much what we we do, is send the playerID (example, getting account Info from a "friend" player). and then we set up the values if they exist.

void GetInfoFromIDCallback (RunCloudScriptResult result)
    {
        JsonObject values = (JsonObject)result.Results;
        object container;
        values.TryGetValue("messageValue", out container);

        string jsonData = PlayFab.SimpleJson.SerializeObject((JsonObject)container);
        UserAccountInfo account = new UserAccountInfo();
        account = PlayFab.SimpleJson.DeserializeObject<UserAccountInfo>(jsonData, Util.ApiSerializerStrategy);

        string faceID = "";
        if (result.ResultsEncoded.Contains("FacebookInfo"))
        {
            faceID = account.FacebookInfo.FacebookId;
        }

        string playfabID = account.PlayFabId;

        string displayName = "";
        if(result.ResultsEncoded.Contains("DisplayName"))
        {
            displayName = account.TitleInfo.DisplayName;
        }
        else
        {
            if (result.ResultsEncoded.Contains("FacebookInfo"))
            {
                displayName = account.FacebookInfo.FullName;
            }
        }

        if(playfabID == playerInfo.localID)
        {
            playerInfo.displayName = displayName;
        }

        if (OnApiResponseWithParam != null)
        {
            OnApiResponseWithParam(playfabID, faceID, displayName);
        }
    }

 

I mean, you are absolutely right, perhaps we could get this information using the client API, but I really want to know IF it is possible to deserialize the UserAccountInfo, since I am pretty sure the same issue happens if I am returning any of the other types (for example the Dictionary<string,UserDataRecord> that I was able to serialize and deserialize).

 

Thanks in advance brendan.

 

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Jose Pablo Monge Chacon avatar image
Jose Pablo Monge Chacon answered

Also... this might be unrelated, but the game is not asking for the secret key anymore :/

if I write

PlayFabSettings.DeveloperSecretKey = secretKey;

it gives me an error... This was straight after upgrading the plugin.

 

 

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

marcowilliamspf avatar image
marcowilliamspf answered

Well I definitely see a couple of things that are strange with they way you are trying to deserialize / serialize objects in your code, however I'm not convinced that it is an issue.

So first let's tackle the issues that I think might be causing a problem.  My first thought is why are you putting the result of your GetUserAccountInfo into another object?   Why not return it as-is?

So your cloudscript would be.
handlers.getUserInfoWithID = function (args)
{
    var getInfo = server.GetUserAccountInfo({
        PlayFabId : args.PlayerID
    });
    

    // Commented these out because of errors.
    //log.debug(getInfo);  <-- this returned errors for me
    //log.debug(getInfo.data); <-- this returned errors for me 
    
    return getInfo;
}

Then in the client code (C#) I did the following.
http://pastebin.com/CtsPCe6T

I was able to get a successful deserialization for UserAccountInfo.


Lastly,  you said that you had trouble with:  PlayFabSettings.DeveloperSecretKey = secretKey;   
This makes me think that you are using the Combined SDK which has the server & client SDK.   Which we do not recommend.  The pure client SDK does not have this field in PlayFabSettings.  So maybe you upgraded to the latest SDK of client only?  


 

 

 

 

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Jose Pablo Monge Chacon avatar image
Jose Pablo Monge Chacon answered

Hello Marco,

 

Thanks a lot for your input, that actually helps a lot. I am definitely confused by the JsonObject class, I think it's simpler than I think.

 

Now, I am getting the right values, but I am going to go through all my playfab code (a lot) to make sure that the data is coming back as it should be.

Regarding the Secret Key, I just deleted every file that would say PlayFab, and still, no way to set the secret key (and the game is actually being able to make calls into the service :O ) Is this on purpose??



Thanks a lot both of you for your help

JP

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

Well, the client should always be able to make calls regardless - the issue is that you can't make Server or Admin API calls without the Secret Key. Which is actually as intended, since you should never ship a version of your game with the Secret Key embedded. That would give hackers the ability (via the Secret Key) to make any Server or Admin call they wanted to. Instead, you should hook up Server API calls via Cloud Script.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Jose Pablo Monge Chacon avatar image
Jose Pablo Monge Chacon answered

Also, checked here

https://github.com/PlayFab/UnitySDK

 

And the client sample ( https://github.com/PlayFab/UnitySDK/tree/master/PlayFabClientSample ) has no mention of the DeveloperSecretKey.

On the other side: (https://github.com/PlayFab/UnitySDK/tree/master/PlayFabServerSample/Assets/PlayFabSDK/Public)

here it can be found under

PlayFabSettings.cs   Which I don't understand why, it kind of makes no sense.   Thanks in advance, JP
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.