反序列化 Google 配置文件响应时出现问题

Problem deserializing Google profile response

我正在 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 我 "seen" json 文件是这样的:

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

显然,引号之间是数据。

我不是很习惯JSon但是看this我觉得格式就是"nameOfProperty":"ValueOfProperty",所以我做了GoogleProfile对象。

我也读到属性 [Preserve][JsonConstructor] 是必需的,因此链接器在编译时不只是 "remove" 清空构造函数。

没有异常,也没有明显的问题,但如果我在最后 return profile.email; 行放置一个断点,我可以看到 json 对象拥有所有数据并且完全没问题,但是profile 对象只有 email 属性 的值为 null...

我不明白:其他属性怎么了?有可能吗?您知道,您使用一堆属性编写一个对象,但创建该对象时只使用其中一个属性吗?如果对象的所有属性的值为null,OK,但是其他属性去哪了?

可以肯定的是,我已经清理并重建了项目和解决方案,删除了 binobj 文件夹,然后再次清理并重建...我已经完成了显而易见的事情。

事情是,正如你在我之前提到的博客中看到的那样,首先我没有使用 GoogleProfile 对象,我只是复制了博客中的对象......只有一个 属性 称为 email。是否有可能 visual studio 或 xamarin 或其他东西被窃听并且更改没有得到反映?我对此表示怀疑,因为我已经更改了 GetStringAsync 方法中使用的 URI,它确实得到了反映,但是,我不知道。

PD:与此同时,我将 JSON 直接解析为普通字符串,它是一个简单的对象,我只真正需要电子邮件,但是,我会很遗憾必须以这种方式解析它,而不是仅仅反序列化它。


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

其中一个属性是布尔值(当然),所以我更改了它,对象现在是:

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 bool email_verified { get; set; }
    public string locale { get; set; }
}

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

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

我的步数:

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

那么,您的账户有问题吗?你的帐户有电子邮件吗?和我的有什么区别吗?

这是我得到的:

代码:

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;
        }
    }
}