jhlee8804
8/3/2017 - 3:41 AM

JsonConverter for nullable fields to default value (string, array)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using Newtonsoft.Json;

namespace Newtonsoft.Json.Serialization
{
    /// <summary>
    /// json 필드 중 string 또는 array의 값이 null일 경우 string.Empty 또는 "[]"으로 치환하여 직렬화한다.
    /// cf. http://stackoverflow.com/questions/23830206/json-convert-empty-string-instead-of-null
    ///
    /// usage)
    ///
    /// JsonSerializerSettings settings = new JsonSerializerSettings();
    /// settings.ContractResolver = new JsonNullToEmptyContractResolver();
    /// vat json = JsonConvert.SerializeObject(value, settings);
    /// </summary>
    public class JsonNullToEmptyContractResolver : CamelCasingExceptDictionaryKeysResolver
    {
        public JsonNullToEmptyContractResolver()
        { }

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            var property = base.CreateProperty(member, memberSerialization);
            if (property != null)
            {
                var propertyType = ((PropertyInfo)member).PropertyType;
                if (propertyType == typeof(string))
                {
                    property.ValueProvider = new NullToEmptyStringProvider(property.ValueProvider);
                }
                else if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>))
                {
                    property.ValueProvider = new NullToEmptyListValueProvider(property.ValueProvider, propertyType);
                }
            }

            return property;
        }

        private class NullToEmptyStringProvider : IValueProvider
        {
            private readonly IValueProvider _provider;

            public NullToEmptyStringProvider(IValueProvider provider)
            {
                _provider = provider;
            }

            public object GetValue(object target)
            {
                var value = _provider.GetValue(target);
                if (value == null)
                {
                    value = string.Empty;
                }

                return value;
            }

            public void SetValue(object target, object value)
            {
                _provider.SetValue(target, value);
            }
        }

        private class NullToEmptyListValueProvider : IValueProvider
        {
            private readonly IValueProvider _provider;
            private readonly object _defaultValue;

            public NullToEmptyListValueProvider(IValueProvider provider, Type propertyType)
            {
                _provider = provider;
                _defaultValue = Activator.CreateInstance(propertyType);
            }

            public object GetValue(object target)
            {
                return _provider.GetValue(target) ?? _defaultValue;
            }

            public void SetValue(object target, object value)
            {
                _provider.SetValue(target, value ?? _defaultValue);
            }
        }
    }
}
}