Error deserializing JSON credential data - Google API

Hello,

I am facing an issue in deserializing the JSON credential data when connecting to Google API. I am building a mobile application to be built for Android. Here is the code I am using to connect to Google API:

byte[] byteArray = Encoding.UTF8.GetBytes(jsonData);
MemoryStream stream = new MemoryStream(byteArray);

ServiceAccountCredential credential = ServiceAccountCredential.FromServiceAccountData(stream);

_sheetsService = new SheetsService(new BaseClientService.Initializer()
{
    HttpClientInitializer = credential,
    ApplicationName = _applicationName
});

I get the JSON data from a remote database via a webservice.

The thing is this code runs perfectly when I test the program in Unity. However, when I build the APK and test it on my phone, I get the error ā€œError deserializing JSON credential dataā€. I am really stuck and would appreciate any help.

Thanks.

PS. I am using Google API v4.

Well I suppose the first step would be to attach the debugger so that you can inspect what value is actually being deserialized at that point if possible. I forget exactly what you need to enable but you will definitely be able to debug/breakpoint the code

Have you actually verified that the content of ā€œjsonDataā€ is actually valid json? Try to drop it in JsonLint or some other json verifier and see if everything is right. Thereā€™s still a chance that there may be some invisible characters (a common issue is a BOM [Byte Order Mark] at the very beginning depending on where the data actually comes from on your webservice side).

I already did that, it works perfectly when running in Unityā€¦ the problem happens when I export to APK. I tried using the logcat to check the json string and it looks fine as well!!!

I downloaded the JSON string from Google API servicesā€¦ it is the credentials key that I use to connect to my google api service. but just to make sure I used the link you provided to verify the json string and it is a valid one.

Which does not address my post at all. I never mentioned the difference when running in the editor, you can debug Android builds too so you can step through line-by-line looking at your data, you do not need to faf around with logging

Out of curiosity, which part/line specifically does it error on? The exception sounds like something I would expect when turning JSON into a C# object for example however this code does not do that so I am just curious what else would throw such an error

The error happens at line 4.

And i would appreciate it if you can direct me to a debugger that debugs android builds.

Visual Studio, just make sure the APK is a development build and script debugging is enabled in the build settings. You can also tick for the app to wait for a debugger to be attached - this means it will not run any code in your application until you tell it to continue (so that you can attach the debugger). I forget exactly what you need to do in Visual Studio but in the debug portion there is an ā€œAttach to Processā€ button you may need to use once your app is started

(This will all need to be while plugged in via USB)

If that doesnā€™t ā€œjust workā€ then try this as well (I have never needed this solution but its something I found) https://discussions.unity.com/t/818934

1 Like

I assume by ā€˜line 4ā€™ you mean

ServiceAccountCredential credential = ServiceAccountCredential.FromServiceAccountData(stream);

I imagine that ServiceAccountCredential is part of the Google library? Do you have the source for that? Can you look inside it?

What do you mean by you downloaded it from the Google API? When I said you should make sure it contains valid JSON, I meant you should check it in the built game when running on the actual device. Try adding a temporary Debug.Log. Use ā€œadb logcatā€ to see the log output.

I was able to debug the APK from VS and I was able to acquire the inner exception. Here is the exception I am getting at line 4:

Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Google.Apis.Auth.OAuth2.JsonCredentialParameters. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.

I did some research and I read some posts about creating a link.xml file that disable bytecode stripping. here is the content of the link.xml I created:

<linker>
    <assembly fullname="AssemblyCSharp">
        <type fullname="Google.Apis.Auth.OAuth2.JsonCredentialParameters">
            <!-- disables stripping just for the constructor -->
            <method signature="System.Void .ctor()"/>
        </type>

        <!-- disables stripping for the entire type -->
        <type fullname="Google.Apis.Auth.OAuth2.JsonCredentialParameters" preserve="all" />
    </assembly>
</linker>

I added that file in the Assets folder and rebuilt the APK but i am still getting the same exception!

2 Likes

Well, now itā€™s clear what the problem is: AOT platform and code stripping :slight_smile:

Your link.xml doesnā€™t seem to be right unless that class is actually compiled into your AssemblyCSharp? I would bet that this is actually located in a seperate assembly, no? A quick search revealed this. So the assembly should be ā€œGoogle.Apis.Auth.dllā€. Since the assembly name seems to be without the extension, try

    <linker>
        <assembly fullname="Google.Apis.Auth">
            <type fullname="Google.Apis.Auth.OAuth2.JsonCredentialParameters" preserve="all" />
        </assembly>
    </linker>

or simply

    <linker>
        <assembly fullname="Google.Apis.Auth" preserve="all"/>
    </linker>

This may be the better solution in case other classes are also needed from that assembly.