JsonConvert.DeserializeObjects 不适用于修剪未使用的代码发布设置

问题描述 投票:0回答:2

JsonConvert.DeserializeObjects 方法在“修剪未使用的代码”发布设置关闭时起作用。当我打开此设置时,我得到:

Newtonsoft.Json.JsonSerializationException: 无法找到一个 用于类型 MyNamespace.MyObject 的构造函数。一个类应该 要么有一个默认构造函数,一个带参数的构造函数或一个 标有 JsonConstructor 属性的构造函数。小路 '命名空间',第 1 行,位置 13.

它是一个简单的对象,没有构造函数。我尝试添加一个没有参数的空白构造函数,没有任何改变。

发布设置

  • 配置:发布 |任何 CPU
  • Target Framework: net7.0-windows10.0.22621.0 -- 在没有操作系统特定目标的情况下使用 net7.0 也会导致这个问题
  • 部署方式:自包含
  • 目标运行时:win - x64
  • 生成单个文件:ON
  • 启用 ReadyToRun 编译:ON
  • 修剪未使用的代码:开 - 关闭此设置会使文件大小加倍,但问题消失了

这是一个与 JsonConvert.DeserializeObjects does not work after Linking SDK and User Assemblies but for Windows 类似的问题。该问题的解决方案对我不起作用。

有人对此问题有任何解决方法吗?

更新:

波纹管是一个最小的例子:

using Newtonsoft.Json;

namespace ConsoleApp1;

internal class Program
{
    static void Main( string[] args )
    {
        var res = JsonConvert.DeserializeObject<Response>( "{ \"blah\": [ { \"name\": \"test\", \"id\": \"test\" }, { \"name\": \"test2\", \"id\": \"test2\" } ] }" );
    }
}

public class Blah
{
    [JsonProperty( "name", NullValueHandling = NullValueHandling.Ignore )]
    public string Name { get; set; } = "";

    [JsonProperty( "id", NullValueHandling = NullValueHandling.Ignore )]
    public string Id { get; set; } = "";
}

public class Response
{
    [JsonProperty( "blah", NullValueHandling = NullValueHandling.Ignore )]
    public List<Blah> SomeList { get; } = new List<Blah>();
}

以上代码在正常编译(Debug 或 Release)时运行良好。使用上述设置发布时会抛出错误:

未处理的异常。 Newtonsoft.Json.JsonSerializationException: 无法找到用于类型 ConsoleApp1.Response 的构造函数。 A 类应该有一个默认构造函数,一个构造函数 参数或标有 JsonConstructor 属性的构造函数。 路径 'blah',第 1 行,位置 9.at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader, JsonObjectContract, JsonProperty , JsonProperty , String , Boolean& ) 在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader , 类型, JsonContract, JsonProperty, JsonContainerContract, JsonProperty,对象)在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader , 类型, JsonContract, JsonProperty, JsonContainerContract, JsonProperty,对象)在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader , 类型, 布尔值) 在 Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader,类型) 在 Newtonsoft.Json.JsonConvert.DeserializeObject(字符串,类型, JsonSerializerSettings)在 Newtonsoft.Json.JsonConvert.DeserializeObject[T](字符串, JsonSerializerSettings) 在 ConsoleApp1.Program.Main(String[]) 中 C:\Users\用户名\来源 epos\MREJsonIssue\ConsoleApp1\Program.cs:行 9

更新二:

针对 .NET 6.0 不会产生此问题。

linker json.net visual-studio-2022 .net-7.0 self-contained
2个回答
1
投票

我发现了两个潜在的解决方法:

  1. 用明确的

    DynamicDependency
    属性标记主要方法:

    [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Response))]
    [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Blah))]
    static void Main( string[] args )
    
  2. 将类移动到单独的程序集并用

    <IsTrimmable>true</IsTrimmable>
    <TrimMode>copyused</TrimMode>

    标记它

附言还有第三种解决方法——使用反射在程序中显式获取两种类型的构造函数(

Console.WriteLine(typeof(Response).GetConstructors().Length);
Console.WriteLine(typeof(Blah).GetConstructors().Length);

同时查看 docs.


0
投票

很难重现你的问题,但你的财产没有任何二传手。添加一个(例如 init)。恕我直言,手动初始化类中的每个属性绝不是个好主意。您应该始终假定此属性为空。这样你就可以避免空引用异常。

public class Response
{
    [JsonProperty( "blah", NullValueHandling = NullValueHandling.Ignore )]
    public List<Blah> SomeList { get; init; } // = new List<Blah>();
}
© www.soinside.com 2019 - 2024. All rights reserved.