开启Trim unused code后JsonConvert.DeserializeObject失效求助
解决.NET7开启代码裁剪后Newtonsoft.Json反序列化失败的问题
问题背景
开启发布设置中的Trim unused code后,调用JsonConvert.DeserializeObject<T>会抛出Newtonsoft.Json.JsonSerializationException,提示无法找到目标类型的构造函数;关闭该设置后功能正常。即使给类添加无参构造函数,问题依然存在,但切换到.NET6环境则无此异常。涉及的发布配置如下:
- 配置:Release | Any CPU
- 目标框架:net7.0 / net7.0-windows10.0.22621.0
- 部署模式:自包含
- 目标运行时:win-x64
- 生成单文件:开启
- 启用ReadyToRun编译:开启
可行解决办法
1. 给目标类添加带[JsonConstructor]标记的无参构造函数
代码裁剪工具会移除未被显式引用的构造函数,即使编译器自动生成了默认无参构造,也可能被误删。显式添加构造函数并标记[JsonConstructor],可以告诉裁剪工具保留该构造供Newtonsoft.Json调用:
public class Response { [JsonConstructor] public Response() {} [JsonProperty( "blah", NullValueHandling = NullValueHandling.Ignore )] public List<Blah> SomeList { get; } = new List<Blah>(); }
2. 通过Trim配置文件保留构造函数
如果不想修改代码,可以在项目中添加Trim描述文件,指定保留目标类的无参构造:
- 在项目文件(.csproj)中添加以下配置:
<ItemGroup> <TrimmerRootDescriptor Include="trim-descriptor.xml" /> </ItemGroup>
- 创建
trim-descriptor.xml文件,内容如下(替换YourAssemblyName为实际程序集名称):
<linker> <assembly fullname="YourAssemblyName"> <type fullname="ConsoleApp1.Response"> <method name=".ctor" /> </type> </assembly> </linker>
3. 替换为System.Text.Json库
.NET7官方的System.Text.Json对代码裁剪的兼容性更好,无需额外配置即可在裁剪模式下正常工作。修改代码如下:
using System.Text.Json; using System.Text.Json.Serialization; namespace ConsoleApp1; internal class Program { static void Main( string[] args ) { var res = JsonSerializer.Deserialize<Response>( "{ \"blah\": [ { \"name\": \"test\", \"id\": \"test\" }, { \"name\": \"test2\", \"id\": \"test2\" } ] }" ); } } public class Blah { [JsonPropertyName( "name" )] public string Name { get; set; } = ""; [JsonPropertyName( "id" )] public string Id { get; set; } = ""; } public class Response { [JsonPropertyName( "blah" )] public List<Blah> SomeList { get; } = new List<Blah>(); }
4. 调整发布设置(临时方案)
如果上述方案都无法使用,可以临时关闭Trim unused code(但会导致发布文件体积翻倍),或者关闭启用ReadyToRun编译——部分场景下能解决构造函数被误删的问题,但会丢失ReadyToRun带来的启动速度优势。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

