Which Json deserializer provides IList <T> collections?

I am trying to deserialize json for an object model where collections are represented as IList<T>

types.

The actual deserialization 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 implicit conversions are. This is the type 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; }
}

      

And this is the type ContactDetail

:

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

      

It is important to know with LazyList<T>

what 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 class definition LazyList<T>

was fine until I tried to deserialize the Json into it. Seems to System.Web.Script.Serialization.JavaScriptSerializer

serialize lists in List<T>

, which makes sense at this age, but I need them in a type IList<T>

, so they'll be injected into mine LazyList<T>

(at least where I think I'm going wrong).

I am getting this exception:

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

      

When I try to use List<ContactDetail>

in my type Contact

(as you can see above) it works. But I don't want to use List<T>

. I even tried to inherit from the LazyList<T>

inheritance List<T>

, which seemed to work, but passing the List<T>

internal T[]

to my implementation was a nightmare and I just don't want the bells and whistles List<T>

anywhere in my model.

I have also tried some other json libraries to no avail (I may not be able to use them fully. I have replaced links more or less and tried to repeat the code at the beginning of this question. Maybe passing parameters to parameters will help?).

I don't know what to try now. Am I going with a different deserializer? Can I customize deserialization? Do I need to change my types to please the deserializer? Do I need to worry more about implicit casting, or just implement a different interface?

+2


source to share


3 answers


I ended up using Json.NET lib which has good linq support for custom mapping. This is what ended up with my deserialization:



        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;

      

0


source


Can't deserialize directly to an interface as interfaces are just a contract. The JavaScriptSerializer must 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 should be fairly simple given the code you posted:



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

      

0


source


Unfortunately, you probably need to fix your class as the deserializer doesn't know it should be of type IList, since List is an implementation of IList.

Since the deserializers at http://json.org have a source available, you can simply modify it to do what you want.

0


source







All Articles