Xamarin.Forms项目中使用Refit 6.1.15时iOS端出现System.Text.Json.JsonSerializer类型初始化异常求助
解决Xamarin.Forms iOS平台Refit调用API时System.Text.Json初始化异常问题
这个iOS平台独有的异常我之前在Xamarin项目里也碰到过,本质是iOS的链接器优化或者AOT编译特性,导致System.Text.Json的必要组件被误删,或是初始化时机出了问题。给你几个针对性的解决方案:
方案一:调整iOS链接器设置,保留System.Text.Json组件
iOS的链接器默认会移除它认为“未被使用”的代码,但System.Text.Json的很多序列化逻辑是反射调用的,链接器识别不出来就会误删相关组件:
- 打开你的iOS项目属性,切换到iOS Build选项卡
- 在Linker Behavior下拉菜单中,选择Link Framework SDKs Only(如果之前选的是
Link All的话);如果必须用Link All来减小包体积,那就添加一个Linker.xml文件到iOS项目中,内容如下:
<linker> <assembly fullname="System.Text.Json" preserve="all"/> </linker>
- 记得把
Linker.xml的Build Action设置为LinkDescription
方案二:切换Refit使用Newtonsoft.Json序列化(兼容性更佳)
System.Text.Json在Xamarin iOS上的兼容性不如Newtonsoft.Json,强制Refit用Newtonsoft.Json可以绕过这个问题:
- 先安装
Refit.Newtonsoft.JsonNuGet包(要和你用的Refit 6.1.15版本匹配) - 修改你的DI配置代码,指定NewtonsoftJson序列化器:
services.AddRefitClient<IAuthorizeApi>(new RefitSettings(new NewtonsoftJsonContentSerializer())) .ConfigureHttpClient(c => c.BaseAddress = new Uri(BaseAddress)) .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15) }));
- 把模型上的
[AliasAs]或者[JsonPropertyName]替换成Newtonsoft.Json的[JsonProperty]特性:
namespace CivicMobile.Models { public class AuthResponse { [JsonProperty("access_token")] public string AccessToken { get; set; } [JsonProperty("token_type")] public string TokenType { get; set; } [JsonProperty("expires_in")] public int ExpiresIn { get; set; } [JsonProperty("userName")] public string Username { get; set; } [JsonProperty("userIdentifier")] public string UserIdentifier { get; set; } [JsonProperty(".issued")] public string IssuedAt { get; set; } [JsonProperty(".expires")] public string ExpiresAt { get; set; } } }
方案三:提前初始化System.Text.Json
有时候异常是因为首次调用时System.Text.Json的初始化延迟导致的,我们可以在iOS项目启动时提前触发初始化:
打开iOS项目的AppDelegate.cs,在FinishedLaunching方法开头添加一行代码:
public override bool FinishedLaunching(UIApplication app, NSDictionary options) { // 提前触发JsonSerializer的初始化,避免延迟加载异常 _ = System.Text.Json.JsonSerializer.Serialize(new object()); // 其他原有代码... global::Xamarin.Forms.Forms.Init(); LoadApplication(new App()); return base.FinishedLaunching(app, options); }
验证步骤
不管用哪个方案,都记得先清理整个解决方案,然后重新编译iOS项目;如果你的iOS项目开启了AOT编译,也要确保在AOT模式下测试,避免漏测问题。
内容的提问来源于stack exchange,提问作者Timothy Belvin
相关产品推荐
相关产品推荐

