最近遇到的一個問題,就是關於 Json.NET 的 SerializeObject 的顯示問題
其實一般狀況下我就是直接無腦的 JsonConvert.SerializeObject(object)
但是,最近在維護一個系統因為物件要改成 Nullable 就有點麻煩,所以看看能不能直接再 SerializeObject
解決盡量的不使用 Attribute 或是改寫 Nullable 去解決

先來說說物件這是我的物件
User.cs:
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public string FriendId { get; set; }
public int Age { get; set; }
public DateTime Birth { get; set; }
public List Colleague { get; set; }
public User CloseFriend { get; set; }
public User()
{
Colleague = new List();
}
}
因為我只填寫了 Id 還有 Name 就直接無腦的 SerializeObject 後你會得到
{"Id":"D1","Name":"DONMA","FriendId":null,"Age":0,"Birth":"0001-01-01T00:00:00","Colleague":[],"CloseFriend":null}
但是,我不希望 null 的值出現,這問題還很簡單 直接使用 NullValueHandling = NullValueHandling.Ignore
var u1 = new User { Id = "D1", Name = "DONMA" };
Result += JsonConvert.SerializeObject(u1,
Newtonsoft.Json.Formatting.None,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
//{"Id":"D1","Name":"DONMA","Age":0,"Birth":"0001-01-01T00:00:00","Colleague":[]}
這時候結果變成
{"Id":"D1","Name":"DONMA","Age":0,"Birth":"0001-01-01T00:00:00","Colleague":[]}
接下來就是萬惡的 DateTime 預設是 0001-01-01T00:00:00 的問題 還有預設 int 是 0 的問題
這時候可以使用 DefaultValueHandling = DefaultValueHandling.Ignore 來解決
var u1 = new User { Id = "D1", Name = "DONMA" };
Result += JsonConvert.SerializeObject(u1,
Newtonsoft.Json.Formatting.None,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
});
//{"Id":"D1","Name":"DONMA","Colleague":[]}
結果:
{"Id":"D1","Name":"DONMA","Colleague":[]}
這時候精彩的來了,對方希望 Colleague 雖然是物件 array 如果是空陣列的時候也不要出現,但是其實我個人習慣
List<object> 在 Ctor 的時候先 new 出來,這時候怎麼辦只好動用 DefaultContractResolver
EmptyListResolver.cs
public class EmptyListResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
Type propType = ((PropertyInfo)member).PropertyType;
property.ShouldSerialize = obj =>
{
if (propType.IsGenericType &&
propType.GetGenericTypeDefinition() == typeof(List<>))
{
return (property.ValueProvider.GetValue(obj) as dynamic).Count > 0;
}
return true;
};
return property;
}
}
這時候 需要在 SerializeObject 加上 ContractResolver = new EmptyListResolver()
var u1 = new User { Id = "D1", Name = "DONMA" };
Result += JsonConvert.SerializeObject(u1,
Newtonsoft.Json.Formatting.None,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
ContractResolver = new EmptyListResolver()
});
//{"Id":"D1","Name":"DONMA"}
結果:
{"Id":"D1","Name":"DONMA"}
大概就是這樣了,花了我一點時間處理 Happy Coding.
reference:
https://stackoverflow.com/questions/46977905/overriding-a-property-value-in-custom-json-net-contract-resolver
https://stackoverflow.com/questions/64552981/newtonsoft-json-defaultcontractresolver-remove-key-from-dictionary
https://stackoverflow.com/questions/37389884/removing-empty-array-members-from-a-json-string