代码之家  ›  专栏  ›  技术社区  ›  Matt Kocaj

哪个JSON反序列化程序呈现IList<t>集合?

  •  2
  • Matt Kocaj  · 技术社区  · 15 年前

    我正试图将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;T & GT; :

    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;T & GT; 所以他们会投进我的 Lazylist<T> (至少我认为这是我出错的地方)。

    我得到这个例外:

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

    当我尝试使用 List<ContactDetail> 在我的 接触 键入(正如您在上面看到的注释)似乎可以工作。但我不想用 列表& T; 是的,我甚至试过 Lazylist<T> 继承 列表& T; 它似乎执行,但通过 列表& T; 内部 T[] 对于我的实现来说是一场噩梦,我只是不希望 列表& T; 在我的模型中的任何地方。

    我也试过一些 other json 图书馆没有用(可能我没有充分利用它们的潜力)。我或多或少地替换了引用,并试图重复这个问题顶部引用的代码。也许传递设置参数会有帮助??)

    我不知道现在该试什么。我是否要使用另一个反序列化程序?我是否调整反序列化本身?是否需要更改类型以使反序列化程序满意?我需要更担心隐式强制转换还是仅仅实现另一个接口?

    3 回复  |  直到 15 年前
        1
  •  0
  •   jrista    15 年前

    不能直接反序列化到接口,因为接口只是一个契约。JavaScriptSerializer必须反序列化为实现IList<t>的某种具体类型,最符合逻辑的选择是List<t>。您必须将列表转换为Lazylist,考虑到您发布的代码,它应该足够简单:

    var list = serializer.Deserialize<IList<Contact>>(...);
    var lazyList = new LazyList(list);
    
        2
  •  0
  •   James Black    15 年前

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

    因为反序列化程序位于 http://json.org 有可用的源,您可以只修改一个来做您想做的。

        3
  •  0
  •   Matt Kocaj    15 年前

    我最终使用了 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;