反序列化Google个人资料响应时出现问题

时间:2019-03-27 18:12:49

标签: c# json xamarin.forms google-oauth xamarin.auth

我正在通过Xamarin.Forms应用向Google进行身份验证。身份验证之后,我想检索用户电子邮件,并使用从this blog改编而成的以下代码,即用于检索电子邮件的代码:

public class GoogleProfile
{
    [Preserve]
    [JsonConstructor]
    public GoogleProfile() { }

    public string sub { get; set; }
    public string name { get; set; }
    public string given_name { get; set; }
    public string profile { get; set; }
    public string picture { get; set; }
    public string email { get; set; }
    public string email_verified { get; set; }
    public string locale { get; set; }
}

public class GoogleService
{
    public async Task<string> GetEmailAsync(string tokenType, string accessToken)
    {
        var httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);
        var json = await httpClient.GetStringAsync("https://www.googleapis.com/oauth2/v3/userinfo");//https://www.googleapis.com/userinfo/email?alt=json");
        var profile = JsonConvert.DeserializeObject<GoogleProfile>(json);
        return profile.email;
    }
}

现在,在最后一行return profile.email中有一个断点,我已经“看到”了这样的json文件:

{
  "sub": "",
  "name": "",
  "given_name": "",
  "profile": "",
  "picture": "",
  "email": "",
  "email_verified": "",
  "locale": "",
}

引号之间是数据。

我不太习惯JSon,但阅读this时认为格式只是"nameOfProperty":"ValueOfProperty",所以我制作了GoogleProfile对象。

我也读到,属性[Preserve][JsonConstructor]是必需的,因此链接器在编译时不仅会“删除”空的构造函数。

没有例外,也没有明显的问题,但是,如果我在最后的return profile.email;行中放置一个断点,则可以看到json对象具有所有数据,并且很好,但是{ {1}}对象只有 profile属性,其值为email ...

我不明白:其他属性发生了什么?可能吗您知道,您对具有一堆属性的对象进行编码,但是仅使用这些属性之一创建该对象吗?如果该对象的所有属性都为null,那么好,但是其他属性又去了哪里?

可以肯定的是,我已经清理并重建项目和解决方案,已经删除了nullbin文件夹,然后再次清理并重建...我已经做了明显的事情

就像您在前面提到的博客中所看到的那样,首先,我没有使用obj对象,我只是在博客中复制了该对象...只有一个名为{{1 }}。 Visual Studio或Xamarin或其他东西有可能被bug窃听并且更改未得到反映吗?我对此表示怀疑,因为我已经更改了GoogleProfile方法中使用的URI,并且确实得到了体现,但是,我不知道。

PD:同时,我将JSON直接解析为普通字符串,它是一个简单的对象,我只需要电子邮件,但是,我不得不以这种方式解析它是一种耻辱。而不是反序列化。


编辑: 正如Skin在评论中所建议的那样,我使用了http://jsonutils.com/

其中一个属性是bool(当然),所以我对其进行了更改,现在的对象是:

email

但是它并没有改变结果,还是一样。断点处的结果图像:

Breakpoint values

1 个答案:

答案 0 :(得分:1)

我认为您的代码没有任何问题。我使用了与您相同的代码,但没有进行任何更改。我使用自己的tokenTypeaccessToken

我的步骤:

  1. 将您的代码复制到我的项目中。
  2. 使用blog中的项目来获取我自己的令牌
  3. 安装newtonsoft Nuget软件包
  4. 运行项目并获得结果

那么,您的帐户有问题吗?您的帐户有电子邮件吗?和我有什么不同吗?

这就是我得到的:

json Result

代码:

public partial class MainPage : ContentPage
{
    public MainPage()
    {

        InitializeComponent();

        testAsync();
    }

    public async Task testAsync()
    {

        GoogleService googleS = new GoogleService();
        // use your token here
        var email = await googleS.GetEmailAsync("", "");
        Console.WriteLine(email);
    }

    public class GoogleProfile
    {
        [Preserve]
        [JsonConstructor]
        public GoogleProfile() { }

        public string sub { get; set; }
        public string name { get; set; }
        public string given_name { get; set; }
        public string profile { get; set; }
        public string picture { get; set; }
        public string email { get; set; }
        public string email_verified { get; set; }
        public string locale { get; set; }
    }

    public class GoogleService
    {
        public async Task<string> GetEmailAsync(string tokenType, string accessToken)
        {
            var httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var json = await httpClient.GetStringAsync("https://www.googleapis.com/oauth2/v3/userinfo");//https://www.googleapis.com/userinfo/email?alt=json");
            var profile = JsonConvert.DeserializeObject<GoogleProfile>(json);

            Console.WriteLine(json);
            Console.WriteLine(profile);


            return profile.email;
        }
    }
}