使用Json.Net将空字符串转换为null

8
我遇到了一个问题,想要找到一种自动将所有的EmptyOrWhiteSpace字符串(服务器端)反序列化为null的方法。Json.Net默认情况下只是将值分配给对象属性,我需要逐个验证每个字符串是否为空或空格,然后将其设置为null。
我需要在反序列化时完成此操作,以便不必记住验证来自客户端的每个字符串。
如何在Json Net上覆盖此功能?

1
http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_NullValueHandling.htm - garfbradaz
2
@garfbradaz 这怎么解决他的问题呢?那个设置是告诉它如何处理 null,而不是如何处理空字符串。 - dmeglio
2
@garfbradaz 我没有需要处理的空值,我有需要转换为 null 的空字符串。 - victor
2
你只需要反转逻辑吗? - Raphaël Althaus
2
不确定为什么这被关闭为不集中?它提出了一个明确的单一问题 - 如何配置Newtonsoft将EmptyString反序列化为Null? - Brondahl
显示剩余5条评论
1个回答

6
经过大量的源代码挖掘,我解决了我的问题。原来所有在评论中提出的解决方案只适用于我反序列化一个包含字符串属性的复杂对象。在这种情况下,是的,简单修改合同解析器就可以解决[1]。
然而,我需要一种方法,在反序列化时将任何字符串转换为null,并且以这种方式修改合同将无法处理我的对象只是一个字符串的情况,即:
public void MyMethod(string jsonSomeInfo)
{
  // At this point, jsonSomeInfo is "\"\"",
  // an emmpty string.

  var deserialized = new JsonSerializer().Deserialize(new StringReader(jsonSomeInfo), typeof(string));

  // deserialized = "", event if I used the modified contract resolver [1].
}

当我们使用复杂对象时,JSON.NET会在内部将TokenType赋值为JsonToken.StartObject,这将导致反序列化按照特定路径进行,其中调用了property.ValueProvider.SetValue(target, value);
然而,如果对象只是一个字符串,则TokenType将为JsonToken.String,路径也将不同,并且值提供程序将永远不会被调用。
无论如何,我的解决方案是构建一个自定义转换器来转换具有TokenType == JsonToken.StringJsonReader(下面是代码)。 解决方案:
public class StringConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
            if (reader.Value == null) return null;

            string text = reader.Value.ToString();

            if (string.IsNullOrWhiteSpace(text))
            {
                return null;
            }

            return text;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException("Not needed because this converter cannot write json");
    }

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

[1] 感谢 @Raphaël Althaus。
public class NullToEmptyStringResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        return type.GetProperties()
        .Select(p => {
            var jp = base.CreateProperty(p, memberSerialization);
            jp.ValueProvider = new EmptyToNullStringValueProvider(p);
            return jp;
        }).ToList();
    }
}

public class EmptyToNullStringValueProvider : IValueProvider
{
    PropertyInfo _MemberInfo;

    public EmptyToNullStringValueProvider(PropertyInfo memberInfo)
    {
        _MemberInfo = memberInfo;
    }

    public object GetValue(object target)
    {
        object result = _MemberInfo.GetValue(target);

        if (_MemberInfo.PropertyType == typeof(string) && result != null && string.IsNullOrWhiteSpace(result.ToString()))
        {
            result = null;
        }

        return result;
    }

    public void SetValue(object target, object value)
    {
        if (_MemberInfo.PropertyType == typeof(string) && value != null && string.IsNullOrWhiteSpace(value.ToString()))
        {
            value = null;
        }

        _MemberInfo.SetValue(target, value);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接