忽略序列化为JSON时引发异常的类成员

忽略序列化为JSON时引发异常的类成员,第1张

忽略序列化为JSON时引发异常的类成员

如果您不控制源代码,则可以

ContractResolver
在序列化过程中使用自定义为有问题的属性注入“
ShouldSerialize”方法。您可以使该方法始终返回false,或者可以选择实现一些逻辑,该逻辑将检测属性将仅在这种情况下抛出并返回false的情况。

例如,假设您的类如下所示:

class Problematic{    public int Id { get; set; }    public string Name { get; set; }    public object Offender     {        get { throw new NullReferenceException(); }    }}

显然,如果我们尝试序列化上述内容,它将无法正常工作,因为

Offender
当序列化程序尝试访问该属性时,该属性始终会引发异常。由于我们知道引起问题的类和属性名称,因此我们可以编写一个自定义ContractResolver(派生自DefaultContractResolver)来抑制该特定成员的序列化。

class CustomResolver : DefaultContractResolver{    protected override JsonProperty CreateProperty(MemberInfo member,        MemberSerialization memberSerialization)    {        JsonProperty property = base.CreateProperty(member, memberSerialization);        if (property.DeclaringType == typeof(Problematic) &&  property.PropertyName == "Offender")        { property.ShouldSerialize = instanceOfProblematic => false;        }        return property;    }}

这是演示如何使用它的演示:

class Program{    static void Main(string[] args)    {        Problematic obj = new Problematic        { Id = 1, Name = "Foo"        };        JsonSerializerSettings settings = new JsonSerializerSettings();        settings.ContractResolver = new CustomResolver();        string json = JsonConvert.SerializeObject(obj, settings);        Console.WriteLine(json);    }}

输出:

{"Id":1,"Name":"Foo"}
更通用的解决方案

在您的评论中,您指出了当访问任何属性时,您可能会抛出多种异常的对象。为此,我们需要更通用的东西。这是一个可能适用于这种情况的解析器,但是您需要在自己的环境中进行广泛的测试。它不依赖于任何特定的类或属性名称,而是为
每个 以其方式出现的属性创建ShouldSerialize谓词。在该谓词中,它使用反射来获取try /
catch内的属性的值。如果成功,则返回true,否则返回false。

class CustomResolver : DefaultContractResolver{    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)    {        JsonProperty property = base.CreateProperty(member, memberSerialization);        property.ShouldSerialize = instance =>        { try {     PropertyInfo prop = (PropertyInfo)member;     if (prop.CanRead)     {         prop.GetValue(instance, null);         return true;     } } catch { } return false;        };        return property;    }}

这是一个演示:

class Program{    static void Main(string[] args)    {        List<MightThrow> list = new List<MightThrow>        { new MightThrow { Flags = ThrowFlags.None, Name = "none throw" }, new MightThrow { Flags = ThrowFlags.A, Name = "A throws" }, new MightThrow { Flags = ThrowFlags.B, Name = "B throws" }, new MightThrow { Flags = ThrowFlags.Both, Name = "both throw" },        };        JsonSerializerSettings settings = new JsonSerializerSettings();        settings.ContractResolver = new CustomResolver();        settings.Formatting = Formatting.Indented;        string json = JsonConvert.SerializeObject(list, settings);        Console.WriteLine(json);    }}[Flags]enum ThrowFlags{    None = 0,    A = 1,    B = 2,    Both = 3}class MightThrow{    public string Name { get; set; }    public ThrowFlags Flags { get; set; }    public string A    {        get        { if ((Flags & ThrowFlags.A) == ThrowFlags.A)     throw new Exception(); return "a";        }    }    public string B    {        get        { if ((Flags & ThrowFlags.B) == ThrowFlags.B)     throw new Exception(); return "b";        }    }}

输出:

[  {    "Name": "none throw",    "Flags": 0,    "A": "a",    "B": "b"  },  {    "Name": "A throws",    "Flags": 1,    "B": "b"  },  {    "Name": "B throws",    "Flags": 2,    "A": "a"  },  {    "Name": "both throw",    "Flags": 3  }]


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5477676.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-12
下一篇 2022-12-12

发表评论

登录后才能评论

评论列表(0条)

保存