Json Преобразует пустую строку вместо null
Я пытаюсь сериализовать свою структуру, чтобы строки, которые не получили значение, получили значение по умолчанию "" вместо null
[JsonProperty(PropertyName = "myProperty", DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue("")]
public string MyProperty{ get; set; }
Мой результат в строке Json:
"myProperty": null,
что я хочу
"myProperty": "",
Я также попытался создать конвертер без какого-либо эффекта, функции Convert и 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("");
}
}
Это не помогает Json.Net. Как десериализовать null как пустую строку?
Ответы
Ответ 1
Это должно работать:
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);
}
}
Ответ 2
Ну, мое решение довольно простое, но не использует функции JSON.NET, просто добавьте backend-поле в ваше свойство:
public class Test
{
private string _myProperty = string.Empty;
[JsonProperty(PropertyName = "myProperty")]
public string MyProperty
{
get { return _myProperty; }
set { _myProperty = value; }
}
}
Edit:
В свойствах свойства С# 6.0 будет доступно:
public class Test
{
[JsonProperty(PropertyName = "myProperty")]
public string MyProperty { get; set;} = "";
}
Ответ 3
Пока принятый ответ указал мне в правильном направлении, он выглядит довольно хрупким. Я не хочу беспокоиться о том, чтобы разрешить список объектов 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);
}
}
}