Json转换空字符串而不是null

Igo*_*ros 34 c# string null json

我正在尝试序列化我的结构,以便没有获得值的字符串获取其默认值""而不是null

[JsonProperty(PropertyName = "myProperty", DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue("")]
public string MyProperty{ get; set; }
Run Code Online (Sandbox Code Playgroud)

我在Json字符串中的结果:

"myProperty": null,
Run Code Online (Sandbox Code Playgroud)

我想要的是

"myProperty": "",
Run Code Online (Sandbox Code Playgroud)

我也试过创建一个没有任何影响的转换器,因为某种原因,转换和WriteJson函数甚至都没有触发:

[JsonProperty(PropertyName = "myProperty")]
[JsonConverter(typeof(NullToEmptyStringConverter))]
public string MyProperty{ get; set; }

class NullToEmptyStringConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(object[]);
    }

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
            writer.WriteValue("");
    }
}
Run Code Online (Sandbox Code Playgroud)

这不利于Json.Net如何将null反序列化为空字符串?

L.B*_*L.B 33

这应该工作:

var settings = new JsonSerializerSettings() { ContractResolver= new NullToEmptyStringResolver() };
var str = JsonConvert.SerializeObject(yourObj, settings);
Run Code Online (Sandbox Code Playgroud)
public class NullToEmptyStringResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        return type.GetProperties()
                .Select(p=>{
                    var jp = base.CreateProperty(p, memberSerialization);
                    jp.ValueProvider = new NullToEmptyStringValueProvider(p);
                    return jp;
                }).ToList();
    }
}

public class NullToEmptyStringValueProvider : IValueProvider
{
    PropertyInfo _MemberInfo;
    public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
    {
        _MemberInfo = memberInfo;
    }

    public object GetValue(object target)
    {
        object result =  _MemberInfo.GetValue(target);
        if (_MemberInfo.PropertyType == typeof(string) && result == null) result = "";
        return result;

    }

    public void SetValue(object target, object value)
    {
        _MemberInfo.SetValue(target, value);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @khellang如果你想做出那么多改变,请提供另一个答案,不要编辑这个.我把它翻了回来. (2认同)

Kir*_*kiy 21

虽然接受的答案指出了我正确的方向,但它看起来很脆弱.我希望担心解决的名单JsonProperty物体和实施IValueResolver自己,当有可用于做,在Json.NET(其中可能有各种优化和角落办案建在一个基本的基于反射的重新实现完美的功能工具惯于).

我的解决方案执行最小的覆盖和解析器替换,以确保只有绝对需要更改的部分才会被实际更改:

public sealed class SubstituteNullWithEmptyStringContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (property.PropertyType == typeof(string))
        {
            // Wrap value provider supplied by Json.NET.
            property.ValueProvider = new NullToEmptyStringValueProvider(property.ValueProvider);
        }

        return property;
    }

    sealed class NullToEmptyStringValueProvider : IValueProvider
    {
        private readonly IValueProvider Provider;

        public NullToEmptyStringValueProvider(IValueProvider provider)
        {
            if (provider == null) throw new ArgumentNullException("provider");

            Provider = provider;
        }

        public object GetValue(object target)
        {
            return Provider.GetValue(target) ?? "";
        }

        public void SetValue(object target, object value)
        {
            Provider.SetValue(target, value);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Uri*_*iil 17

好吧,我的解决方案非常简单,但不使用JSON.NET功能,只需将backend字段添加到您的属性:

public class Test
{
    private string _myProperty = string.Empty;

    [JsonProperty(PropertyName = "myProperty")]
    public string MyProperty
    {
        get { return _myProperty; }
        set { _myProperty = value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

在c#6.0中,属性初始化将可用:

public class Test
{
    [JsonProperty(PropertyName = "myProperty")]
    public string MyProperty { get; set;} = "";
}
Run Code Online (Sandbox Code Playgroud)

  • 没有什么可以阻止您调用 MyProperty = null; 因此回到空字符串。 (2认同)

Ton*_*ony 5

@Kirill Shlenskiy的解决方案很棒,但是没有考虑该NullValueHandling属性。

[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Remark{ get; set; }
Run Code Online (Sandbox Code Playgroud)

这是将要解决的改进版本。如果NullValueHandling.Ignore设置为if 并且该值为null,那么它将在JSON输出中被跳过。

public sealed class SubstituteNullWithEmptyStringContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (property.PropertyType == typeof(string))
        {
            // Wrap value provider supplied by Json.NET.
            property.ValueProvider = new NullToEmptyStringValueProvider(property.ValueProvider, property.NullValueHandling);
        }
        return property;
    }

    sealed class NullToEmptyStringValueProvider : IValueProvider
    {
        private readonly IValueProvider Provider;
        private readonly NullValueHandling? NullHandling;

        public NullToEmptyStringValueProvider(IValueProvider provider, NullValueHandling? nullValueHandling)
        {
            Provider = provider ?? throw new ArgumentNullException("provider");
            NullHandling = nullValueHandling;
        }

        public object GetValue(object target)
        {
            if (NullHandling.HasValue 
                && NullHandling.Value == NullValueHandling.Ignore
                && Provider.GetValue(target) == null )
            {
                return null;
            }
            return Provider.GetValue(target) ?? "";
        }

        public void SetValue(object target, object value)
        {
            Provider.SetValue(target, value);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)