>我正在尝试序列化一些"懒惰创建"各种列表的遗留对象。我无法更改旧行为。
我把它归结为这个简单的例子:
public class Junk
{
protected int _id;
[JsonProperty( PropertyName = "Identity" )]
public int ID
{
get
{
return _id;
}
set
{
_id = value;
}
}
protected List<int> _numbers;
public List<int> Numbers
{
get
{
if( null == _numbers )
{
_numbers = new List<int>( );
}
return _numbers;
}
set
{
_numbers = value;
}
}
}
class Program
{
static void Main( string[] args )
{
Junk j = new Junk( ) { ID = 123 };
string newtonSoftJson = JsonConvert.SerializeObject( j, Newtonsoft.Json.Formatting.Indented );
Console.WriteLine( newtonSoftJson );
}
}
目前的结果是:{ "身份":123, "数字": []}
我想得到:{ "身份":123}
也就是说,我想跳过任何列表、集合、数组或空的东西。
如果您没有找到解决方案,那么当您设法追踪它时,答案非常简单。
如果允许您扩展原始类,则向其添加ShouldSerializePropertyName
函数。 这应该返回一个布尔值,指示是否应为类的当前实例序列化该属性。 在您的示例中,这可能如下所示(未经过测试,但您应该得到图片):
public bool ShouldSerializeNumbers()
{
return _numbers.Count > 0;
}
这种方法对我有用(尽管是 VB.NET)。 如果您不被允许修改原始类,那么链接页面上描述的IContractResolver
方法是要走的路。
关于大卫琼斯使用IContractResolver
的建议,这对我有用,可以在不显式修改需要序列化的类的情况下涵盖所有IEnumerables
变体:
public class ShouldSerializeContractResolver : DefaultContractResolver
{
public static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.PropertyType != typeof(string)) {
if (property.PropertyType.GetInterface(nameof(IEnumerable)) != null)
property.ShouldSerialize =
instance => (instance?.GetType().GetProperty(property.PropertyName).GetValue(instance) as IEnumerable<object>)?.Count() > 0;
}
return property;
}
}
然后我把它构建到我的设置对象中:
static JsonSerializerSettings JsonSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = ShouldSerializeContractResolver.Instance,
};
并像这样使用它:
JsonConvert.SerializeObject(someObject, JsonSettings);
> Bryan 你最需要实例变量的开销,你需要捕获字段和成员实例,而且我不会运行计数操作,这需要枚举来耗尽整个集合,你可以简单地运行 MoveNext() 函数。
public class IgnoreEmptyEnumerableResolver : CamelCasePropertyNamesContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member,
MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.PropertyType != typeof(string) &&
typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
property.ShouldSerialize = instance =>
{
IEnumerable enumerable = null;
// this value could be in a public field or public property
switch (member.MemberType)
{
case MemberTypes.Property:
enumerable = instance
.GetType()
.GetProperty(member.Name)
?.GetValue(instance, null) as IEnumerable;
break;
case MemberTypes.Field:
enumerable = instance
.GetType()
.GetField(member.Name)
.GetValue(instance) as IEnumerable;
break;
}
return enumerable == null ||
enumerable.GetEnumerator().MoveNext();
// if the list is null, we defer the decision to NullValueHandling
};
}
return property;
}
}
只是为了成为悬念的普通花园,我将 if 测试构建为:
public bool ShouldSerializecommunicationmethods()
{
if (communicationmethods != null && communicationmethods.communicationmethod != null && communicationmethods.communicationmethod.Count > 0)
return true;
else
return false;
}
因为空列表通常也是空的。感谢您发布解决方案。ATB。