Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json Convert empty string instead of null

Tags:

json

string

c#

null

I'm trying to serialize my struct so that the strings that didn't get a value get their default value "" instead of null

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

My result in the Json string:

"myProperty": null,

what i want

"myProperty": "",

I also tried creating a converter without any effect, the can Convert and WriteJson functions aren't even firing for some reason:

[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("");
    }
}

This isnt helping either Json.Net How to deserialize null as empty string?

like image 665
Igor Meszaros Avatar asked May 23 '14 13:05

Igor Meszaros


2 Answers

This should work:

var settings = new JsonSerializerSettings() { ContractResolver= new NullToEmptyStringResolver() }; var str = JsonConvert.SerializeObject(yourObj, settings); 

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);     } } 
like image 135
L.B Avatar answered Sep 30 '22 04:09

L.B


While the accepted answer pointed me in the right direction, it appears quite brittle. I do not want to worry about resolving the list of JsonProperty objects and implementing IValueResolver myself when there are perfectly functional tools available for doing that in Json.NET (which could have all kinds of optimizations and corner case handling built in that a basic reflection-based reimplementation won't).

My solution performs minimal overriding and resolver substitution to ensure that only parts that absolutely need to change are actually altered:

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);
        }
    }
}
like image 45
Kirill Shlenskiy Avatar answered Sep 30 '22 04:09

Kirill Shlenskiy