我有一个这样的对象:
public class MyCollec
{
public ICollection<MyObject> MyCollection { get; set; }
public MyCollec()
{
MyCollection = new List<MyObject>();
}
}
在WebApi中,我的webApiConfig中有一个SerializationBinder:
jsonFormatter.SerializerSettings.Binder = new DefaultSerializationBinder();
当我调用我的控制器返回我的所有对象时,我得到一个像这样的结构
{
"MyCollection": [
{
...
},
{
...
}
]
}
但是如果我用hashset改变我的构造函数
public MyCollec()
{
MyCollection = new HashSet<MyObject>();
}
我的控制器的结果是这样的:
{
"MyCollection": {
"$type": "System.Collections.Generic.HashSet`1[[WebApplication1.Models.MyObject, WebApplication1]], System.Core",
"$values": [
{
...
},
{
...
}
]
}
}
我想明白为什么?导致这种行为的区别是什么?
是否可以使用HashSet但是给出与列表相同的结果?
编辑:
@Grundy评论:
TypeNameHandling属性为Auto,来自doc:包含.NET类型 当被序列化的对象的类型不相同时的名称 它的声明类型。所以似乎HashSet序列化与它不一样 声明的类型。
这是真的,这是原因,但为什么它不适用于List?类型与ICollection不同,如HashSet ......
此外,我尝试更改TypeNameHandling属性,但只有在继承的对象上没有set $ type选项...
http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm
答案 0 :(得分:0)
感谢@Grundy的线索。
我保持
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
我有一个自定义的JsonConverter来改变HashSet的序列化
public class HashSetArrayConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
IEnumerable collectionObj = (IEnumerable)value;
writer.WriteStartObject();
foreach (object currObj in collectionObj)
{
serializer.Serialize(writer, currObj);
}
writer.WriteEndObject();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize(reader, objectType);
}
public override bool CanConvert(Type objectType)
{
var canConvert = IsAssignableToGenericType(objectType, typeof(HashSet<>));
return canConvert;
}
private static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
if (interfaceTypes.Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == genericType))
{
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
}
并将其添加到config:
中jsonFormatter.SerializerSettings.Converters.Add(new HashSetArrayConverter());