如果该值为null,Json.NET不会调用我的自定义转换器

时间:2014-06-09 04:56:24

标签: c# json json.net

我坚持这个问题一天。 我创建的自定义转换器将空字符串转换为空字符串。 我发现如果字符串有空值,Json.NET不会调用我的转换器。 我试图设置我能做的一切,但Json.NET仍然没有将该空字符串发送到自定义转换器。 这是我的转换器代码

using System;
using Newtonsoft.Json;
using log4net;

namespace TestProject.Utils.Jsons
{
  public class NullStringConverter : JsonConverter
  {
    private ILog _log = LogManager.GetLogger("Noonswoon.Utils");

    public override bool CanRead { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        _log.Debug("call NullStringConverter");

        var strValue = value as string;
        if (string.IsNullOrEmpty(strValue))
        {
            _log.Debug("string is null");
            writer.WriteValue(String.Empty);
        }
        else
        {
            _log.DebugFormat("string is not null with value: {0}", strValue);
            writer.WriteValue(strValue);
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotSupportedException();
    }

    public override bool CanConvert(Type objectType)
    {
        _log.DebugFormat("NullStringConverter can convert:{0}", objectType);
        return objectType == typeof(string);
    }
  }
}


        [Test]
    public void SerializeProperty_NullString_ConverterToEmptyString()
    {

    var settings = new JsonSerializerSettings
       {
           Formatting = Formatting.Indented,
           ContractResolver = new SpecialContractResolver(),
           NullValueHandling = NullValueHandling.Include,
           DefaultValueHandling = DefaultValueHandling.Include,

       };
        settings.Converters.Add(new NullStringConverter());

        var user = new User()
        {
            FirstName = null,
        };
        var resultString = JsonConvert.SerializeObject(user, settings);
        Console.WriteLine(resultString);

    }

和输出

{
  "Id": 0,
  "Guid": "00000000-0000-0000-0000-000000000000",
  "Height": 0.0,
  "Friends": null,
  "FirstName": null,
  "Credit": 0.0,
  "CreateDate": "0001-01-01T00:00:00+00:00",
  "LastUpdate": "0001-01-01T00:00:00+00:00",
  "DateOfBirth": "0001-01-01T00:00:00",
  "FriendCount": 0,
  "FriendIds": null
}

这不会像我预期的那样返回空字符串,非常感谢你

public class Friend
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string FacebookId { get; set; }
}

public class User
{
    public int Id;
    public Guid? Guid { get; set; }
    public float Height { get; set; }
    public List<Friend> Friends { get; set; }
    public string FirstName { get; set; }
    public double? Credit { get; set; }
    public DateTimeOffset CreateDate { get; set; }
    public DateTimeOffset? LastUpdate { get; set; }
    public DateTime? DateOfBirth { get; set; }
    public long FriendCount { get; set; }
    public string[] FriendIds { get; set; }
}






    using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json.Serialization;
using log4net;

namespace TestProject.Utils.Jsons
{
    public class SpecialContractResolver : DefaultContractResolver
    {
        private ILog _log = LogManager.GetLogger("SpecialContractResolver");

        protected override IValueProvider CreateMemberValueProvider(MemberInfo member)
        {
            //if only property
            if (member.MemberType == MemberTypes.Property)
            {
                var pi = (PropertyInfo)member;

                _log.DebugFormat("propertyName: {0} ", pi.Name);

                if (pi.PropertyType.IsGenericType && pi.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    return new NullableValueProvider(member, pi.PropertyType.GetGenericArguments().First());

                }

            //if (pi.PropertyType.IsImplementationOf(typeof(ICollection<>)) 
            //    || pi.PropertyType.IsImplementationOf(typeof(ICollection)) 
            //    || pi.PropertyType.IsArray)
            //{
            //       pi.GetValue( 
            //}

            }
            //else if (member.MemberType == MemberTypes.Field)
            //{
            //    var fi = (FieldInfo)member;
            //    if (fi.FieldType.IsGenericType && fi.FieldType.GetGenericTypeDefinition() == typeof(Nullable<>))
            //        return new NullableValueProvider(member, fi.FieldType.GetGenericArguments().First());
            //}

            return base.CreateMemberValueProvider(member);
        }

        protected override System.Collections.Generic.IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
        {

            var properties = CreateProperties(type, memberSerialization);
            foreach (var property in properties)
            {
                _log.DebugFormat("property.PropertyName:{0}", property.PropertyName);
            }
            return properties;
        }

    }
}

2 个答案:

答案 0 :(得分:0)

声明属性

 private string _FirstName=string.Empty;

    public string FirstName
    {
        get { return _FirstName; }
        set { _FirstName = value; }
    }

在此声明中,默认值为空。

您可以通过

等代码处理
 var myObject = new MyObject();
foreach( var propertyInfo in myObject.GetType().GetProperties() )
{
    if(propertyInfo.PropertyType == typeof(string))
    {
        if( propertyInfo.GetValue( myObject, null ) == null )
        {
            propertyInfo.SetValue( myObject, string.Empty, null );
        }
    }
}

答案 1 :(得分:0)

为了让您的转换器执行,您必须使用JsonConverter属性自定义转换器来包装要序列化/反序列化的类:

[JsonConverter(typeof(NullStringConverter))]
public class User
{
   public int Id;
   public Guid? Guid { get; set; }
   public float Height { get; set; }
   public List<Friend> Friends { get; set; }
   public string FirstName { get; set; }
   public double? Credit { get; set; }
   public DateTimeOffset CreateDate { get; set; }
   public DateTimeOffset? LastUpdate { get; set; }
   public DateTime? DateOfBirth { get; set; }
   public long FriendCount { get; set; }
   public string[] FriendIds { get; set; }
}

您可以通过向属性添加DefaultValue属性来实现相同的输出(这是IMO更容易的方式):

[JsonConverter(typeof(NullStringConverter))]
public class User
{
   [JsonProperty(PropertyName = "id", DefaultValueHandling = DefaultValueHandling.Populate]
   [DefaultValue(string.Empty)] 
   public int Id;
   // The rest of the properties..
}