如果您不控制源代码,则可以
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 }]
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)