【问题标题】:JSon.Net specific JSonConverter issue, empty array must be ignoredJSon.Net 特定的 JSonConverter 问题,必须忽略空数组
【发布时间】:2017-04-06 18:47:34
【问题描述】:

我注意到序列化中的奇怪行为。 不过,我有设置

var SerializerSettings = new JsonSerializerSettings() {
                   NullValueHandling = NullValueHandling.Ignore,     DefaultValueHandling= DefaultValueHandling.Ignore}
SerializerSettings.Converters.Add(new JsonArrayToNullConverter());

  var val = new company()
   {
       name = "Bobo Company Renamed"
   }
 var str = JsonConvert.SerializeObject(val, SerializerSettings );

结果将是: {"document_type":2,"locations":null, ...

如果没有自定义转换器,它将是 {"document_type":2,"locations":[], ...

你明白了吗?

但是,由于它变为 null,它 - 应该 - 监听 NullValueHandling = NullValueHandling.Ignore 但很明显,牛顿看的是要序列化的对象值,而不是发出的 writer.WriteNull();

:(

有什么解决方法吗?我在这上面花了几个小时。谢谢!

using Newtonsoft.Json;

using System;
using System.Collections;
using System.Collections.Generic;

namespace Company.Model.TypeConverters
{
    /// <summary>
    /// undo's the forced array creation because OData needs it, but for PATCH, we want no [] empty collections, it is considered to be a 
    /// </summary>
    public class JsonArrayToNullConverter : JsonConverter
    {

        public override bool CanConvert(Type objectType)
        {
            var canConvert = objectType.IsArray || (objectType.IsGenericType && objectType.GetGenericTypeDefinition().IsAssignableFrom(typeof(IEnumerable<>)));
            return canConvert;
        }
        public override bool CanRead
        {
            get
            {
                return false;
            }
        }
        public override bool CanWrite
        {
            get
            {
                return true;
            }
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var enumerator = (IEnumerable)value;

            if (enumerator != null && enumerator.GetEnumerator().MoveNext() == false)
            {
                writer.WriteNull();
                //value = null;
                return;
            }
            serializer.Serialize(writer, value);
        }
    }
}

【问题讨论】:

    标签: serialization json.net


    【解决方案1】:

    解决方案似乎是使用一个 contractresolver 并将其设置在 JsonSerializerSettings 上。

     public class NullToEmptyListResolver : DefaultContractResolver
    {
        protected override IValueProvider CreateMemberValueProvider(MemberInfo member)
        {
            IValueProvider provider = base.CreateMemberValueProvider(member);
    
            if (member.MemberType == MemberTypes.Property)
            {
                Type propType = ((PropertyInfo)member).PropertyType;
                if (propType.IsArray || ( propType.IsGenericType &&
                    propType.GetGenericTypeDefinition().IsAssignableFrom(typeof(IEnumerable<>))))
                {
                    return new EmptyListValueProvider(provider, propType);
                }
            }
    
            return provider;
        }
    
        public class EmptyListValueProvider : IValueProvider
        {
            private readonly IValueProvider innerProvider;
    
            public EmptyListValueProvider(IValueProvider innerProvider, Type listType)
            {
                this.innerProvider = innerProvider;
            }
    
            public void SetValue(object target, object value)
            {
                throw new NotImplementedException();
            }
    
            public object GetValue(object target)
            {
                var val = innerProvider.GetValue(target) ;
                if (val == null) return null;
                var enumerator = (IEnumerable)val;
                return enumerator.GetEnumerator().MoveNext() == false ? null : val;
            }
        }
    

    【讨论】:

    • 在您的SetValue() 方法中,您应该调用innerProvider.SetValue(target, value); 而不是抛出异常。另外,使用后考虑disposing the enumerator。例如。 this answer 隐含地做到了。
    猜你喜欢
    • 2014-10-09
    • 1970-01-01
    • 2017-01-27
    • 2016-12-23
    • 1970-01-01
    • 2018-01-16
    • 2021-03-06
    • 2020-11-06
    • 1970-01-01
    相关资源
    最近更新 更多