我有以下类定义:
public class Tag
{
public Guid? TagId { get; set; }
public string TagText { get; set; }
public DateTime CreatedOn { get; set; }
}
public class Wiki
{
public Guid? WikiId { get; set; }
public string WikiText { get; set; }
public string Title { get; set; }
public DateTime CreatedOn { get; set; }
public IEnumerable<Tag> Tags { get; set; }
}
从数据库中我得到以下json对象:
{
"WikiId": "83981284-0AD3-4420-90AB-15E3BF6BD7B7",
"WikiText": "Text",
"Title": "Title",
"CreatedOn": "2017-08-07T09:16:06.0800000",
"Tags": [{}] // <-- here i would like to ignore the empty Tag object
}
当我现在做JsonConvert.DeserializeObject<Wiki>(json)
时,我得到一个带有1个Tag的列表的Wiki对象,其值为TagId: null, TagText: null and CreatedOn: "0001-01-01T00:00:00"
在反序列化时有没有办法忽略空Tag对象?我尝试了几个JsonSerializerSettings,但没有任何帮助。
答案 0 :(得分:4)
您可以使用自定义JsonConverter
在反序列化期间忽略空对象。这样的事情可以奏效:
class IgnoreEmptyItemsConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsAssignableFrom(typeof(List<T>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
List<T> list = new List<T>();
JArray array = JArray.Load(reader);
foreach (JObject obj in array.Children<JObject>())
{
if (obj.HasValues)
{
list.Add(obj.ToObject<T>(serializer));
}
}
return list;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用转换器,只需在[JsonConverter]
属性中添加Tags
属性,如下所示:
public class Wiki
{
...
[JsonConverter(typeof(IgnoreEmptyItemsConverter<Tag>))]
public IEnumerable<Tag> Tags { get; set; }
}
答案 1 :(得分:2)
您必须在转换后检测空标记对象并自行删除它们。从反序列化程序的角度来看,{}
是一个完全有效且完整的Tag
对象,其属性都未设置。
以下内容应该有效(假设C#6):
Wiki wiki = JsonConvert.DeserializeObject<Wiki>(json);
wiki.Tags = Wiki.Tags?.Where(x => x.TagId.HasValue)?.ToList();
答案 2 :(得分:1)
由于@ Brian-Rogers的出色回答,我得以提出一种非通用解决方案,该解决方案适用于所有馆藏,而不仅仅是List
:
public class IgnoreEmptyArrayItemsConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
bool result = typeof(System.Collections.IEnumerable).IsAssignableFrom(objectType);
return result;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var tokenIndexesToRemove = new List<int>();
var array = JArray.Load(reader);
for (int i = 0; i < array.Count; i++)
{
var obj = array[i];
if (!obj.HasValues)
tokenIndexesToRemove.Add(i);
}
foreach (int index in tokenIndexesToRemove)
array.RemoveAt(index);
var result = array.ToObject(objectType, serializer);
return result;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
此解决方案不会循环遍历对象,反序列化它们并将它们逐个添加到硬编码的List
集合中,而是会从JArray
中删除有问题的令牌并让库将整个数组反序列化为应有的类型。
用法:
public class Wiki
{
...
[JsonConverter(typeof(IgnoreEmptyItemsConverter))] // No generic parameter needed
public HashSet<Tag> Tags { get; set; }
}