如果该值为null,则Json.NET不会调用我的自定义转换器 [英] Json.NET not call my custom converter if that value is null
问题描述
这个问题困扰了我一天. 我创建的自定义转换器会将空字符串转换为空字符串. 我发现,如果字符串的值为空,则Json.NET不会调用我的转换器. 我尝试设置所有可以设置的内容,但Json.NET仍未将空字符串发送到自定义转换器. 这是我的转换器代码
I am stuck with this problem for a day. The custom converter that I created will convert null string to empty string. I found that if the string has null value Json.NET not call my converter. I 've tried to setting everything that I can but Json.NET still not send that null string to custom converter. This is my converter code
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
}
不按预期返回空字符串,非常感谢
Which not return empty string as I expected , thank you so much
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;
}
}
}
推荐答案
为使您的转换器执行,您必须使用要自定义的转换器使用JsonConverter
属性包装要序列化/反序列化的类:
In order for your converter to execute you have to wrap the class you want to serialize/deserialize with the custom converter with a JsonConverter
attribute:
[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的更简单方法):
You may achieve the same output by adding a DefaultValue
attribute to your properties (which is the easier way IMO):
[JsonConverter(typeof(NullStringConverter))]
public class User
{
[JsonProperty(PropertyName = "id", DefaultValueHandling = DefaultValueHandling.Populate]
[DefaultValue(string.Empty)]
public int Id;
// The rest of the properties..
}
这篇关于如果该值为null,则Json.NET不会调用我的自定义转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!