You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何RequiresUnreferencedCodeAttribute使JsonSerializer.Deserialize重载不可用?

解决.NET6类库中调用带[RequiresUnreferencedCode]的JsonSerializer.Deserialize重载问题

问题原因

你遇到的并非编译器“找不到方法”,而是代码修剪兼容性的编译拦截。.NET6及后续版本的类库项目默认启用了可修剪性分析——即便你没主动开启代码修剪,编译器也会检查代码是否符合修剪安全标准。那个接受Utf8JsonReader和JsonSerializerOptions的Deserialize重载因内部依赖反射,被标记了[RequiresUnreferencedCode]特性,所以编译器会阻止你调用它,除非你明确声明代码不支持修剪。

解决方案

方案1:禁用可修剪性分析

如果你的类库不需要支持代码修剪,直接在项目文件(.csproj)中添加以下配置关闭修剪分析:

<PropertyGroup>
  <EnableTrimAnalyzer>false</EnableTrimAnalyzer>
</PropertyGroup>

配置生效后,编译器将不再检查修剪兼容性,你可正常调用目标重载。

方案2:声明类不支持修剪(NuGet包推荐)

作为NuGet包,建议明确告知使用者你的代码不兼容修剪。需在整个转换器类上添加[RequiresUnreferencedCode]特性(仅标记单个Read方法无效,因为框架会调用转换器实例的方法,需标记整个类型):

using System.Diagnostics.CodeAnalysis;

[RequiresUnreferencedCode("该JSON转换器依赖的反序列化方法使用反射,不支持代码修剪。")]
internal class MyJsonConverter : JsonConverter<ISomeInterface>
{
    public override void Write(
        Utf8JsonWriter writer,
        ISomeInterface value,
        JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(
            writer,
            value.ToSerializableConfig(),
            options);
    }

    public override ISomeInterface? Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options)
    {
        var deserializedObj = JsonSerializer.Deserialize<SerializableClass>(
            reader,
            options);
        
        ISomeInterface? converted = null;

        var successfulConversion =
            ConcreteTypeA.TryFromSerializable(deserializedObj, out converted)
            || ConcreteTypeB.TryFromSerializable(deserializedObj, out converted)
            || ConcreteTypeC.TryFromSerializable(deserializedObj, out converted);

        return converted;
    }
}

添加特性后,编译器会允许你调用目标重载;同时当使用者的项目开启修剪时,会收到明确警告,知晓你的包不兼容修剪。

方案3:兼容修剪的替代实现(复杂但安全)

若必须支持修剪,不能依赖该重载,需手动解析Utf8JsonReader内容构造SerializableClass对象,规避反射。示例如下:

public override ISomeInterface? Read(
    ref Utf8JsonReader reader,
    Type typeToConvert,
    JsonSerializerOptions options)
{
    if (reader.TokenType != JsonTokenType.StartObject)
    {
        throw new JsonException();
    }

    var serializableObj = new SerializableClass();
    while (reader.Read())
    {
        if (reader.TokenType == JsonTokenType.EndObject)
        {
            break;
        }

        if (reader.TokenType == JsonTokenType.PropertyName)
        {
            var propName = reader.GetString();
            reader.Read();
            switch (propName)
            {
                case nameof(SerializableClass.Property1):
                    serializableObj.Property1 = reader.GetInt32();
                    break;
                case nameof(SerializableClass.Property2):
                    serializableObj.Property2 = reader.GetString();
                    break;
                // 依次处理其他属性
            }
        }
    }

    // 后续转换逻辑保持不变
    ISomeInterface? converted = null;
    var successfulConversion =
        ConcreteTypeA.TryFromSerializable(serializableObj, out converted)
        || ConcreteTypeB.TryFromSerializable(serializableObj, out converted)
        || ConcreteTypeC.TryFromSerializable(serializableObj, out converted);

    return converted;
}

这种方式完全不依赖反射,兼容代码修剪,但需手动编写所有属性的解析逻辑,适合对修剪兼容性有严格要求的场景。


内容的提问来源于stack exchange,提问作者Jacob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 09:43:28