【问题标题】:ISet<T> serialization to JSON using DataContractJsonSerializer使用 DataContractJsonSerializer 将 ISet<T> 序列化为 JSON
【发布时间】:2015-06-04 18:10:47
【问题描述】:

我正在做一些测试来检查/理解 JSON 序列化到/从 C# 中的 .Net 类型。 我正在尝试使用 DataContractJsonSerializer。

这是我尝试序列化的示例类型:

[DataContract]
[KnownType(typeof(HashSet<int>))]
public class TestModel
{
    [DataMember]
    public string StreetName { get; private set; }
    [DataMember]
    public int StreetId { get; private set; }
    [DataMember]
    public int NumberOfCars { get; set; }
    [DataMember]
    public IDictionary<string, string> HouseDetails { get; set; }
    [DataMember]
    public IDictionary<int, string> People { get; set; }
    [DataMember]
    public ISet<int> LampPosts { get; set; }

    public TestModel(int StreetId, string StreetName)
    {
        this.StreetName = StreetName;
        this.StreetId = StreetId;

        HouseDetails = new Dictionary<string, string>();
        People = new Dictionary<int, string>();
        LampPosts = new HashSet<int>();
    }

    public void AddHouse(string HouseNumber, string HouseName)
    {
        HouseDetails.Add(HouseNumber, HouseName);
    }

    public void AddPeople(int PersonNumber, string PersonName)
    {
        People.Add(PersonNumber, PersonName);
    }

    public void AddLampPost(int LampPostName)
    {
        LampPosts.Add(LampPostName);
    }
}

当我尝试使用 DataContractJsonSerializer 序列化此类型的对象时,我收到以下错误:

{"'System.Collections.Generic.HashSet`1[System.Int32]' is a collection type and cannot be serialized when assigned to an interface type that does not implement IEnumerable ('System.Collections.Generic.ISet`1[System.Int32]'.)"}

这个消息对我来说听起来不对。 ISet&lt;T&gt; 确实实现了 IEnumerable&lt;T&gt;( 以及 IEnumerable)。 如果在我的 TestModel 类中,我替换

public ISet<int> LampPosts { get; set; }

public ICollection<int> LampPosts { get; set; }...

然后一切顺利。

我是 JSON 新手,因此我们将不胜感激任何帮助

【问题讨论】:

  • 为什么需要HashSetISet
  • 在实际应用程序中,“LampPosts”将是引用类型的集合。 LampPosts 不允许重复,并且很可能使用 NHibernate 填充。我相信 ISet 在这种情况下是一个不错的选择。
  • 创建一个模型包装器来为你做这件事。
  • 不确定您所说的模型包装器是什么意思,或者这在这种情况下有何帮助。上面的类可能是领域模型的一部分。它封装了数据和行为。 ORM 工具(如 NHibernate)允许我将我的域对象“状态”直接保存到数据库或从数据库保存。我不应该/不需要添加另一个间接级别(如包装器)。
  • 即使我们确实调查了包装器路线,我在这里想要理解的是为什么我原来的帖子中的场景不起作用。

标签: .net json


【解决方案1】:

看起来这是known microsoft bug。 支持的接口列表在框架中是硬编码的,ISet 不是其中之一:

CollectionDataContract.CollectionDataContractCriticalHelper._knownInterfaces = new Type[]
{
  Globals.TypeOfIDictionaryGeneric,
  Globals.TypeOfIDictionary,
  Globals.TypeOfIListGeneric,
  Globals.TypeOfICollectionGeneric,
  Globals.TypeOfIList,
  Globals.TypeOfIEnumerableGeneric,
  Globals.TypeOfICollection,
  Globals.TypeOfIEnumerable
};

是的,错误信息不正确。 所以,DataContractJsonSerializer 不能序列化ISet 接口,它应该被替换为支持的接口之一,或者用具体的ISet 实现。

【讨论】:

    猜你喜欢
    • 2011-11-21
    • 2011-04-27
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多