哪个 Json 反序列化器将 IList呈现为收藏品?
我正在尝试将 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>IListLazyList
中(至少我认为我出错的地方)。
我收到此异常:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不可能直接反序列化到接口,因为接口只是一个契约。 JavaScriptSerializer 必须反序列化为实现 IList的某种具体类型,最合乎逻辑的选择是 List。您必须将列表转换为 LazyList,鉴于您发布的代码,这应该很容易:
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:
不幸的是,您可能需要修复您的类,因为反序列化器无法知道它应该是 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.
我最终使用了 Json.NET lib,它对自定义映射具有良好的 linq 支持。这就是我的反序列化最终的样子:
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: