【问题标题】:TypeInfoResolver Modifier doesn't resolve correct type - it resolves base type instead of real typeTypeInfoResolver 修饰符不解析正确的类型 - 它解析基本类型而不是真实类型
【发布时间】:2023-01-27 23:07:45
【问题描述】:

我很难用 System.Text.Json TypeInfoResolver Modifier 替换 Newtonsoft 的 ContractResolver。

我有一个 ContractResolver 只负责序列化特定的属性:

public sealed class BaseExceptionContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
    public BaseExceptionContractResolver()
    {
        NamingStrategy = new Newtonsoft.Json.Serialization.CamelCaseNamingStrategy();
    }

    protected override IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
    {
        Debug.WriteLine($"Type in Newtonsoft.Json: {type}");
        return !type.IsSubclassOf(typeof(BaseException)) ? base.CreateProperties(type, memberSerialization) : base.CreateProperties(typeof(BaseException), memberSerialization).Where(IsExceptionProperty).ToList();
    }

    private bool IsExceptionProperty(Newtonsoft.Json.Serialization.JsonProperty property)
    {
        if (property.PropertyName == null)
        {
            return false;
        }

        return property.PropertyName.Equals(nameof(BaseException.Type), StringComparison.InvariantCultureIgnoreCase)
               || property.PropertyName.Equals(nameof(BaseException.Details), StringComparison.InvariantCultureIgnoreCase)
               || property.PropertyName.Equals(nameof(BaseException.Description), StringComparison.InvariantCultureIgnoreCase);
    }
}

我使用 System.Text.Json 创建了类似的逻辑:

public static  class Modifiers
{
    public static void OnlyBaseExceptionProperties(System.Text.Json.Serialization.Metadata.JsonTypeInfo typeInfo)
    {
        Debug.WriteLine($"Type in System.Text.Json: {typeInfo.Type}");

        if (!typeInfo.Type.IsSubclassOf(typeof(BaseException)))
        {
            return;
        }

        foreach (var property in typeInfo.Properties)
        {
            if (property.Name.Equals(nameof(BaseException.Type), StringComparison.InvariantCultureIgnoreCase)
                || property.Name.Equals(nameof(BaseException.Details), StringComparison.InvariantCultureIgnoreCase)
                || property.Name.Equals(nameof(BaseException.Description), StringComparison.InvariantCultureIgnoreCase))
            {
                property.ShouldSerialize = static (_, _) => true;
            }
            else
            {
                property.ShouldSerialize = static (_, _) => false;
            }
        }
    }
}

我在我的测试应用程序中使用它:

internal class Program
{
    static void Main(string[] args)
    {
        var baseExceptionContractResolver = new BaseExceptionContractResolver();

        var newtonsoftSettings = new Newtonsoft.Json.JsonSerializerSettings
            { Formatting = Newtonsoft.Json.Formatting.Indented, ContractResolver = baseExceptionContractResolver };

        var textJsonSettings = new System.Text.Json.JsonSerializerOptions
        {
            PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase,
            WriteIndented = true,
            TypeInfoResolver = new DefaultJsonTypeInfoResolver
            {
                Modifiers = { Modifiers.OnlyBaseExceptionProperties }
            }
        };

        Exception exception1 = new ValidationException("Test");
        var exception2 = new ValidationException("Test");

        var s1e1 = Newtonsoft.Json.JsonConvert.SerializeObject(exception1, newtonsoftSettings);
        var s2e1 = System.Text.Json.JsonSerializer.Serialize(exception1, textJsonSettings);

        Console.WriteLine(s1e1 == s2e1);

        var s1e2 = Newtonsoft.Json.JsonConvert.SerializeObject(exception2, newtonsoftSettings);
        var s2e2 = System.Text.Json.JsonSerializer.Serialize(exception2, textJsonSettings);

        Console.WriteLine(s1e2 == s2e2);

            
        Console.ReadLine();
    }
}

输出是:

False
True

当我将类型指定为 Exception 时,传递给 ContractResolver 中的 CreateProperty 的类型是正确的: 但是传递给我的修饰符的类型不正确:

当我使用 var 时,一切都按预期工作,但我想在我的全局异常处理程序逻辑中使用它,因此应该解析正确的类型。

我不确定这是 TypeInfoResolver 中的错误还是我的代码中的错误以及如何修复它。
我创建了一个显示此行为的简单项目:https://github.com/Misiu/JsonSerializerTests

【问题讨论】:

    标签: c# json.net system.text.json .net-7.0


    【解决方案1】:

    这里的问题是:

    var s2e1 = System.Text.Json.JsonSerializer.Serialize(exception1, textJsonSettings);
    

    使用泛型Serialize&lt;TValue&gt;(TValue, JsonSerializerOptions)方法,它不执行实际类型检查,而是使用泛型参数来确定序列化类型,即GetTypeInfo&lt;TValue&gt;(options)。您可以通过将调用更改为以下内容来解决问题:

    var s2e1 = System.Text.Json.JsonSerializer.Serialize(exception1, exception1.GetType(), textJsonSettings);
    

    或者查看polymorphic type serialization,或者为异常创建自定义序列化程序。

    【讨论】:

      猜你喜欢
      • 2022-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多