Json.如果该值为空,则不调用我的自定义转换器

本文关键字:调用 我的 自定义 转换器 如果 Json | 更新日期: 2023-09-27 18:07:45

我被这个问题困了一天。我创建的自定义转换器将把空字符串转换为空字符串。我发现,如果字符串有空值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;
        }
    }
}

Json.如果该值为空,则不调用我的自定义转换器

将属性声明为

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

为了让您的转换器执行,您必须将您想要序列化/反序列化的类与具有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..
}