哪个 Json 反序列化器将 IList呈现为收藏品?

发布于 2024-08-07 21:55:20 字数 2601 浏览 3 评论 0原文

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

实际的反序列化在这里:

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 需要了解的重要一点是它实现了 < code>IList

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 类定义很好,直到我尝试将 Json 反序列化到其中。 System.Web.Script.Serialization.JavaScriptSerializer 似乎想要将列表序列化为 List 这很有意义,因为它的年龄,但我需要它们的类型 < code>IList这样它们就会投射到我的 LazyList 中(至少我认为我出错的地方)。

我收到此异常:

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

当我尝试在我的 Contact 类型中使用 List 时(如您在上面评论的那样),它似乎有效。但我不想使用 List 的。我什至尝试让我的 LazyList 继承自 List ,它似乎执行但传递了 List 的内部T[] 对我的实现来说是一场噩梦,我只是不想在模型中的任何地方出现 List 的臃肿。

我还尝试了一些 其他 json 库,但无济于事(我可能没有使用这些充分发挥了它们的潜力。我或多或少地替换了引用并尝试重复这个问题顶部引用的代码也许传递设置参数会有所帮助?

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

I'm trying to deserialize json to an object model where the collections are represented as IList<T> types.

The actual deserializing is here:

JavaScriptSerializer serializer = new JavaScriptSerializer();

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

Before i post the exception i'm getting you should know what the implicit conversions are. This is the Contact type:

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; }
}

And this is the ContactDetail type:

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

The important thing to know with the LazyList<T> is that it implements 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;
    }

Now this LazyList<T> class definition was fine until i tried deserializing Json into it. The System.Web.Script.Serialization.JavaScriptSerializer seems to want to serialize lists to List<T> which makes sense coz of it's age but i need them in the type IList<T> so they will cast into my LazyList<T> (at least that's where i think i am going wrong).

I get this exception:

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

When i try using List<ContactDetail> in my Contact type (as you can see commented above) it seems to work. But i dont want to use List<T>'s. I even tried having my LazyList<T> inheriting from List<T> which seemed to execute but passing the List<T>'s internal T[] to my implementation was a nightmare and i simply don't want the bloat of List<T> anywhere in my model.

I also tried some other json libraries to no avail (it's possible i may not be using these to their full potential. I more or less replaced the references and attempted to repeat the code quoted at the top of this question. Maybe passing settings params will help??).

I dont know what to try now. Do i go with another deserializer? Do i tweak the deserializing itself? Do i need to change my types to please the deserializer? Do i need to worry more about implicit casting or just implement another interface?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

尹雨沫 2024-08-14 21:55:20

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

var list = serializer.Deserialize<IList<Contact>>(...);
var lazyList = new LazyList(list);

It is not possible to deserialize directly to an interface, as interfaces are simply a contract. The JavaScriptSerializer has to deserialize to some concrete type that implements IList<T>, and the most logical choice is List<T>. You will have to convert the List to a LazyList, which given the code you posted, should be easy enough:

var list = serializer.Deserialize<IList<Contact>>(...);
var lazyList = new LazyList(list);
余罪 2024-08-14 21:55:20

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

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

Unfortunately you will probably need to fix your class, as there is no way for a deserializer to know that it should be of type IList, since List is an implementation of IList.

Since the deserializers at http://json.org have source available you could just modify one to do what you want.

暮倦 2024-08-14 21:55:20

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

I ended up using the Json.NET lib which has good linq support for custom mapping. This is what my deserializing ended up looking like:

        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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文