1

I notice weird behavior in the Serialization. Though, I have the settings

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 );

The result would be: {"document_type":2,"locations":null, ...

Without the custom converter, it would be {"document_type":2,"locations":[], ...

you get the point?

But, since it becomes null, it -should- listen to NullValueHandling = NullValueHandling.Ignore but obviously, Newton, looks at the object value to be serialized, not at the issued writer.WriteNull();

:(

Any workaround? I've spent some hours on this. Thanks!

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);
        }
    }
}
Egbert Nierop
  • 2,066
  • 1
  • 14
  • 16

1 Answers1

0

The solution seemed to be using a contractresolver and set that on the 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;
        }
    }
Egbert Nierop
  • 2,066
  • 1
  • 14
  • 16
  • In your `SetValue()` method you should call `innerProvider.SetValue(target, value);` rather than throw an exception. Also, consider [disposing the enumerator](https://stackoverflow.com/q/232558/3744182) after using it. E.g. [this answer](https://stackoverflow.com/a/24706061/3744182) does it implicitly. – dbc Apr 06 '17 at 19:52