【问题标题】:Convert empty strings to null with Json.Net使用 Json.Net 将空字符串转换为 null
【发布时间】:2020-06-05 00:38:33
【问题描述】:

我无法找到自动反序列化(服务器端)所有 EmptyOrWhiteSpace 字符串到 null 的方法。 Json.Net默认只是简单的给object属性赋值,我需要逐个字符串验证是空还是空格,然后设置为null。

我需要在反序列化时完成此操作,因此我不必记住验证来自客户端的每个字符串。

如何在 Json Net 上覆盖它?

【问题讨论】:

  • @garfbradaz 这如何解决他的问题?该设置告诉它如何处理 null,而不是如何处理空白字符串。
  • @garfbradaz 我没有需要处理的空值,我有需要转换为空的空字符串。
  • stackoverflow.com/a/23832417/961526 : 你只需要反转逻辑吗?
  • 不知道为什么会因为注意力不集中而关闭?这是一个明确的问题 - 如何配置 Newtonsoft 以将 EmptyString 反序列化为 Null?

标签: c# json.net


【解决方案1】:

经过大量的源代码挖掘,我解决了我的问题。 事实证明,只有在我反序列化包含字符串属性的复杂对象时,cmets 中提出的所有解决方案才有效。 在这种情况下,是的,只需修改合约解析器即可 [1]。

但是,我需要一种在反序列化时将 any 字符串转换为 null 的方法,并且在我的对象只是一个字符串的情况下,以这种方式修改合同将失败,即, p>

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 在内部将 JsonToken.StartObjectTokenType 分配给读取器,这将导致反序列化遵循调用 property.ValueProvider.SetValue(target, value); 的特定路径。

但是,如果对象只是一个字符串,则TokenType 将是JsonToken.String,并且路径将不同,并且永远不会调用值提供者。

无论如何,我的解决方案是构建一个自定义转换器来转换具有TokenType == JsonToken.StringJsonReaders(代码如下)。

解决方案

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多