牛顿软件 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 );
    }
}

目前的结果是:{ "身份":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。

相关内容

  • 没有找到相关文章

最新更新