Json.NET从自动属性初始化程序获取默认值

编程入门 行业动态 更新时间:2024-10-11 13:28:50
本文介绍了Json.NET从自动属性初始化程序获取默认值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想减少使用默认值生成的字符串 Json.NET .

I want to reduce the string Json.NET generates by using default values.

我的属性之一是:

public string Name { get; set; } = "Jennifer";

我已经使用了自动属性初始化程序,因此如果为空,则填充该字符串.

I already use the auto-property initializer so the string gets populated if empty.

在使用Json.NET进行序列化时,我使用DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,因此只有更改后的属性才能保留.

When serializing with Json.NET I use DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate so only changed properties get persisted.

我知道我可以像这样使用DefaultValueAttribut:

I know that I can use the DefaultValueAttribut like this:

[DefaultValue("Jennifer")] public string Name { get; set; } = "Jennifer";

但是我想知道是否可以跳过此属性,并在序列化时使用自动属性初始值作为默认值.

But I am wondering if I can skip this attribute and use auto-property initial values as default value when serializing.

推荐答案

是的,您可以使用自定义的ContractResolver来完成此操作,例如以下示例.它的工作方式是为每个Type创建一个引用实例(假定Type是一个类,并且具有默认的构造函数),然后在每个属性上设置一个ShouldSerialize谓词,以根据引用检查该属性的当前值实例.如果它们匹配,则ShouldSerialize返回false,并且该属性未序列化.

Yes, you can do this using a custom ContractResolver such as the one below. It works by creating a reference instance for each Type (assuming the Type is a class and has a default constructor available) and then setting a ShouldSerialize predicate on each property which checks the current value of the property against the reference instance. If they match, then ShouldSerialize returns false and the property is not serialized.

class CustomResolver : DefaultContractResolver { protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { IList<JsonProperty> props = base.CreateProperties(type, memberSerialization); if (type.IsClass) { ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes); if (ctor != null) { object referenceInstance = ctor.Invoke(null); foreach (JsonProperty prop in props.Where(p => p.Readable)) { prop.ShouldSerialize = instance => { object val = prop.ValueProvider.GetValue(instance); object refVal = prop.ValueProvider.GetValue(referenceInstance); return !ObjectEquals(val, refVal); }; } } } return props; } private bool ObjectEquals(object a, object b) { if (ReferenceEquals(a, b)) return true; if (a == null || b == null) return false; if (a is IEnumerable && b is IEnumerable && !(a is string) && !(b is string)) return EnumerableEquals((IEnumerable)a, (IEnumerable)b); return a.Equals(b); } private bool EnumerableEquals(IEnumerable a, IEnumerable b) { IEnumerator enumeratorA = a.GetEnumerator(); IEnumerator enumeratorB = b.GetEnumerator(); bool hasNextA = enumeratorA.MoveNext(); bool hasNextB = enumeratorB.MoveNext(); while (hasNextA && hasNextB) { if (!ObjectEquals(enumeratorA.Current, enumeratorB.Current)) return false; hasNextA = enumeratorA.MoveNext(); hasNextB = enumeratorB.MoveNext(); } return !hasNextA && !hasNextB; } }

要使用解析器,您需要将其添加到JsonSerializerSettings并将设置传递给SerializeObject方法,如下所示:

To use the resolver you need to add it to the JsonSerializerSettings and pass the settings to the SerializeObject method like this:

JsonSerializerSettings settings = new JsonSerializerSettings { ContractResolver = new CustomResolver(), }; string json = JsonConvert.SerializeObject(yourObject, settings);

这是一个有效的演示: dotnetfiddle/K1WbSP

Here is a working demo: dotnetfiddle/K1WbSP

有关此解决方案的一些说明:

Some notes on this solution:

  • 使用此解析器具有优于DefaultValue属性的功能优势,因为它可以处理复杂的默认值,例如Lists,Dictionaries和子对象(前提是您已在子对象上正确实现了Equals方法)类).属性只能处理简单的常量表达式(例如字符串,枚举和其他基元).但是,如果您所需要的只是简单的默认值,请注意,此解析器的性能可能会比仅使用属性稍差一些,因为它需要使用其他反射来实例化引用对象并比较所有属性值.因此,需要进行一些权衡.如果您的JSON很小,那么您可能不会注意到其中的区别.但是,如果您的JSON很大,那么您可能需要做一些基准测试.

  • Using this resolver has a functional advantage over DefaultValue attributes in that it can handle complex defaults like Lists, Dictionaries and child objects (provided you have correctly implemented the Equals method on the child classes). Attributes can only handle simple constant expressions (e.g. strings, enums and other primitives). However, if all you need is simple defaults, be aware that this resolver will probably perform slightly worse than just using the attributes because it needs to use additional reflection to instantiate the reference objects and compare all the property values. So there is a little bit of a tradeoff. If your JSON is small, you probably won't notice a difference. But if your JSON is large, then you may want do some benchmarks.

您可能希望实现类级别的退出机制(例如,解析器查找的自定义属性,或者可能传递给解析器的类名列表),以防万一要做的地方,是要为某些类而不是其他类序列化默认值.

You may want to implement a class-level opt-out mechanism (i.e. a custom attribute that the resolver looks for, or maybe a list of class names that you pass to the resolver) in case you run into situations where you do want the default values to be serialized for certain classes but not others.

更多推荐

Json.NET从自动属性初始化程序获取默认值

本文发布于:2023-07-15 13:12:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1111416.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:初始化   默认值   属性   程序   Json

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!