値を取得できなかった文字列がnullではなくデフォルト値「」を取得するように、構造体をシリアル化しようとしています
[JsonProperty(PropertyName = "myProperty", DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue("")]
public string MyProperty{ get; set; }
Json文字列での私の結果:
"myProperty": null,
私が欲しいもの
"myProperty": "",
また、効果のないコンバーターを作成しようとしましたが、Can 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をデシリアライズする方法?
これは動作するはずです:
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);
}
}
受け入れられた答えは私を正しい方向に向けましたが、それは非常に脆いようです。 I しない Json.NETでそれを行うための完全に機能的なツールがある場合、JsonProperty
オブジェクトのリストを解決し、IValueResolver
を自分で実装することを心配したい(これは基本的なリフレクションベースの再実装ではない、あらゆる種類の最適化とコーナーケース処理を組み込むことができます)。
私のソリューションは、最小限のオーバーライドとリゾルバの置換を実行して、変更するabsolutely needの部分のみが実際に変更されるようにします。
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);
}
}
}
さて、私のソリューションは非常に単純ですが、JSON.NET機能を使用せず、プロパティにバックエンドフィールドを追加するだけです。
public class Test
{
private string _myProperty = string.Empty;
[JsonProperty(PropertyName = "myProperty")]
public string MyProperty
{
get { return _myProperty; }
set { _myProperty = value; }
}
}
編集:
C#6.0では、プロパティの初期化が利用可能になります。
public class Test
{
[JsonProperty(PropertyName = "myProperty")]
public string MyProperty { get; set;} = "";
}
@Kirill Shlenskiyのソリューションは優れていますが、NullValueHandling
属性を考慮していません。
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Remark{ get; set; }
これは、それを処理する改善されたバージョンです。 NullValueHandling.Ignore
が設定され、値が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);
}
}
}