在发布模式下,NewtonSoft 不会将 json 反序列化为对象

NewtonSoft is not deserializing json to object when in release mode

我的 Android Xamarin Forms 应用程序遇到了一个奇怪的错误。无法找到它的根本原因。以下是我的代码,它获取 API 响应并将其反序列化为一个对象。

public async static Task<T2> ExecuteRequest<T1, T2>(T1 t1, EndPoint endPoint, bool getParams = false, HttpVerb method = HttpVerb.POST)
{
    string resStr = "";
    try
    {
        object data = t1;
        if (endPoint.ToString() != EndPoints.Login.ToString() && getParams == false)
              data = Newtonsoft.Json.JsonConvert.SerializeObject(t1);
        HttpUtils.RestClient restClient = new HttpUtils.RestClient(APIPath + endPoint, HttpVerb.POST, data.ToString());
        restClient.ContentType = "application/json";
        restClient.Method = method;
        resStr = await (endPoint != EndPoints.Login && getParams == false ? restClient.MakeRequest() : restClient.MakeRequest(data.ToString()));

        if (string.IsNullOrEmpty(resStr))
            return default(T2);
            
        return Newtonsoft.Json.JsonConvert.DeserializeObject<T2>(resStr);
    }   
    catch (Newtonsoft.Json.JsonSerializationException e)
    {
        Device.BeginInvokeOnMainThread(async () => await Application.Current.MainPage.DisplayAlert("Error", e.Message + "\n----------\n" + resStr, "OK"));
        return default(T2);
    }
    catch (System.Net.WebException)
    {
        Device.BeginInvokeOnMainThread(async () => await Application.Current.MainPage.DisplayAlert("Not Connected", "Please check your Internet connection and restart the app.", "OK"));
        return default(T2);
    }
}

以下是我尝试使用上述方法登录后端系统的方式:

Services.API.ResponseModels.Login res = await APIAccess.ExecuteRequest<string, Services.API.ResponseModels.Login>(req, APIAccess.EndPoints.Login);

对象Class:

public class Login
{
    public string access_token { get; set; }
    public string token_type { get; set; }
    public int expires_in { get; set; }
    public string userName { get; set; }
    public string issued { get; set; }
    public string expires { get; set; }
}

我正确收到了以下 JSON 格式的回复:

{
    "access_token": "<access token received here>",
    "token_type": "bearer",
    "expires_in": 2591999,
    "userName": "<userName received here>",
    ".issued": "Sun, 16 Jan 2022 09:41:06 GMT",
    ".expires": "Tue, 15 Feb 2022 09:41:06 GMT"
}

但在调试模式下,NewtonSoft 正确反序列化它并将用户带到另一个屏幕,而在发布模式下,它显示以下错误:

我尝试正常添加默认构造函数并使用 [JsonConstructor] 属性,但它不起作用。我清理并删除了所有项目中的 Bin 和 Obj,还更新了 NewtonSoft JSON 包。在 Release 模式下似乎没有任何效果。

那么为什么你不使用新的 T2() 而不是默认的 (T2) 来尝试呢?

为此,您需要在定义操作时定义 new(),class。

这是一个 linker 问题,您需要提示它不应删除该构造函数,因为它永远不会被直接调用。

一个技巧是创建一个 class,类似 LinkerPleaseInclude 的东西,并创建提示通常会被 link 淘汰的东西的用法的方法。确保告诉编译器不要 link 使用 [Preserve] 属性去掉这个 class。

这可能看起来像:

[Preserve(AllMembers = true)]
public class LinkerPleaseInclude
{
    public void Include(Login login)
    {
        login = new Login();
    }
}

然后对所有需要它的类型执行此操作。

您可以将 PreserveAttribute 添加到您的 class 图书馆:

public sealed class PreserveAttribute : Attribute
{
    public bool AllMembers;
    public bool Conditional;
    public PreserveAttribute (bool allMembers, bool conditional)
    {
        AllMembers = allMembers;
        Conditional = conditional;
    }
    public PreserveAttribute ()
    {
    }
}

然后在您的 JSON model/class:

上使用该属性
[Preserve(AllMembers = true)]
public class Login
{
    public string access_token { get; set; }
    public string token_type { get; set; }
    public int expires_in { get; set; }
    public string userName { get; set; }
    public string issued { get; set; }
    public string expires { get; set; }
}