2

我正在尝试将 json 反序列化为一个对象模型,其中集合表示为IList<T>类型。

实际的反序列化在这里:

JavaScriptSerializer serializer = new JavaScriptSerializer();

return serializer.Deserialize<IList<Contact>>(
    (new StreamReader(General.GetEmbeddedFile("Contacts.json")).ReadToEnd()));

在我发布异常之前,我让你应该知道隐式转换是什么。这是Contact类型:

public class Contact
{
    public int ID { get; set; }
    public string Name { get; set; }
    public LazyList<ContactDetail> Details { get; set; }
    //public List<ContactDetail> Details { get; set; }
}

这是ContactDetail类型:

public class ContactDetail
{
    public int ID { get; set; }
    public int OrderIndex { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }
}

重要的是要知道LazyList<T>它实现IList<T>

public class LazyList<T> : IList<T>
{
    private IQueryable<T> _query = null;
    private IList<T> _inner = null;
    private int? _iqueryableCountCache = null;


    public LazyList()
    {
        this._inner = new List<T>();
    }

    public LazyList(IList<T> inner)
    {
        this._inner = inner;
    }

    public LazyList(IQueryable<T> query)
    {
        if (query == null)
            throw new ArgumentNullException();
        this._query = query;
    }

现在这个LazyList<T>类定义很好,直到我尝试将 Json 反序列化到它中。System.Web.Script.Serialization.JavaScriptSerializer似乎想要将列表序列化为有意义的列表,因为List<T>它的年龄但我需要它们的类型IList<T>,以便它们将转换为我的LazyList<T>(至少那是我认为我出错的地方)。

我得到这个例外:

System.ArgumentException: Object of type 'System.Collections.Generic.List`1[ContactDetail]' cannot be converted to type 'LazyList`1[ContactDetail]'..

当我尝试List<ContactDetail>在我的Contact类型中使用时(如您在上面所见),它似乎有效。但我不想使用List<T>'s. 我什至尝试让我的LazyList<T>继承List<T>似乎执行,但是将List<T>' 内部传递T[]给我的实现是一场噩梦,我根本不希望List<T>我的模型中任何地方都膨胀。

我还尝试了其他一些 json库但无济于事(我可能没有充分利用这些库。我或多或少地替换了引用并尝试重复此问题顶部引用的代码。也许传递设置参数将帮助??)。

我不知道现在该尝试什么。我要使用另一个解串器吗?我是否调整反序列化本身?我需要改变我的类型来取悦反序列化器吗?我是否需要更多地担心隐式转换或只是实现另一个接口?

4

3 回答 3

0

不可能直接反序列化为接口,因为接口只是一个合同。JavaScriptSerializer 必须反序列化为实现 IList<T> 的具体类型,最合乎逻辑的选择是 List<T>。您必须将 List 转换为 LazyList,鉴于您发布的代码,这应该很容易:

var list = serializer.Deserialize<IList<Contact>>(...);
var lazyList = new LazyList(list);
于 2009-10-18T05:27:39.110 回答
0

不幸的是,您可能需要修复您的类,因为反序列化器无法知道它应该是 IList 类型,因为 List 是 IList 的实现。

由于http://json.org上的反序列化器有可用的源代码,您只需修改一个即可完成您想要的操作。

于 2009-10-18T05:31:09.960 回答
0

我最终使用了Json.NET lib,它对自定义映射有很好的 linq 支持。这就是我的反序列化最终的样子:

        JArray json = JArray.Parse(
            (new StreamReader(General.GetEmbeddedFile("Contacts.json")).ReadToEnd()));

        IList<Contact> tempContacts = (from c in json
                                       select new Contact
                                       {
                                           ID = (int)c["ID"],
                                           Name = (string)c["Name"],
                                           Details = new LazyList<ContactDetail>(
                                               (
                                                   from cd in c["Details"]
                                                   select new ContactDetail
                                                   {
                                                       ID = (int)cd["ID"],
                                                       OrderIndex = (int)cd["OrderIndex"],
                                                       Name = (string)cd["Name"],
                                                       Value = (string)cd["Value"]
                                                   }
                                                ).AsQueryable()),
                                           Updated = (DateTime)c["Updated"]
                                       }).ToList<Contact>();

        return tempContacts;
于 2009-10-29T13:48:22.673 回答