Phi*_*ell 54 c# serialization list json.net
我试图序列化一些"懒惰创建"各种列表的遗留对象.我无法改变遗留行为.
我把它归结为这个简单的例子:
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 );
}
}
Run Code Online (Sandbox Code Playgroud)
目前的结果是:{"身份":123,"数字":[]}
我想得到:{"身份":123}
也就是说,我想跳过任何列表,集合,数组或其他空的东西.
Dav*_*ull 73
如果您没有找到解决方案,那么当您设法跟踪它时,答案非常简单.
如果允许扩展原始类,则向其添加一个ShouldSerializePropertyName函数.这应该返回一个布尔值,指示是否应该为该类的当前实例序列化该属性.在您的示例中,这可能看起来像这样(未经测试,但您应该得到图片):
public bool ShouldSerializeNumbers()
{
return _numbers.Count > 0;
}
Run Code Online (Sandbox Code Playgroud)
这种方法适用于我(尽管在VB.NET中).如果您不允许修改原始类,则IContractResolver链接页面上描述的方法是可行的方法.
布莱恩,你是最不需要实例变量的开销的方式,你需要捕获字段和成员实例,而且我不会运行计数操作,这需要枚举来耗尽整个集合,你可以简单地运行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;
}
}
Run Code Online (Sandbox Code Playgroud)
关于David Jones的使用建议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.GetInterface(nameof(IEnumerable)) != null)
property.ShouldSerialize =
instance => (instance?.GetType().GetProperty(property.PropertyName).GetValue(instance) as IEnumerable<object>)?.Count() > 0;
return property;
}
}
Run Code Online (Sandbox Code Playgroud)
然后将其构建到我的设置对象中:
static JsonSerializerSettings JsonSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = ShouldSerializeContractResolver.Instance,
};
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
JsonConvert.SerializeObject(someObject, JsonSettings);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25657 次 |
| 最近记录: |