This project is read-only.


Unable to cast object of type 'System.Object' to type 'System.Collections.IList'.


Hi I'm using fastJSON to serialize and deseralize streams of, among other, kinect skeletons. Since it's message based I've used a Dictionary<string,object> to serialize the data - everthing works just like a charm except for deseralizing any message containing skeletons. It will then throw cast exception.

The class I use as container to serialize looks like this.

public sealed class MessageRecordProducer
// All except byte[] data goes here
public Dictionary<string,object> Items { get; set; }
// Used for byte[] arrays manually converting the strings using base64 decoder.
public Dictionary<string, object> Data { get; set; }  

the exception is thrown when:
var rec = JSON.Instance.ToObject<MessageRecordProducer>(bodystring);

and the bodystring in this case is attached as test.json


file attachments

Closed Jul 15, 2016 at 2:51 PM by MGholam


MGholam wrote Feb 6, 2014 at 6:26 PM

Unfortunately I cannot check the json since I don't have the assemblies.

The error seems to because probably the Skeleton type has IList as a property and fastJSON doesn't work with interfaces this way when deserializing.

solo95 wrote Feb 6, 2014 at 10:51 PM

Hi and thanks for a prompt answer.

I've attached the kmv.filespersistence dll and the kinect.dll if you want to try :)

Do fastjson support serializing collection implementing IEnumerable? since all skeleton collections are implementing IEnumerable<CollectionType>, IEnumerable.

However they do expose a indexed property, can this be a problem, is there a workaround, can one intercept the serialization or do I need to do Parse and use those KV pairs to reconstruct the serialized object?

an example of indexer in a IEnumerable<T>,IEnumerable implementing ms kinect class:
public Joint this[JointType jointType] { get; set; }


MGholam wrote Feb 7, 2014 at 6:38 AM

I will try and take a look, in the meantime if you are on .net 4 try ToDynamic() and see if that helps.

solo95 wrote Feb 7, 2014 at 7:09 AM

Hi again,

I've replaces the current with the following (see below). However it seems like the type (in my case 2) is not introduced in the returned IList<Type> instead a IList<Object> (wanted IList<Skeleton>) - I'll do this search manually but it seems like a bug (or I'm using this completely insane way :) ?


( "Microsoft.Kinect.Skeleton, Microsoft.Kinect, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35": "2",)

var parse = JSON.Instance.Parse(bodystring);
  var dict = (IDictionary<string, object>)parse;
  var items = (Dictionary<string,object>)dict["Items"];

  object data;
  dict.TryGetValue("Data", out data);

  return new MessageRecordProducer { Data = data as Dictionary<string,object>, Items = items };

solo95 wrote Feb 7, 2014 at 7:31 AM

Hmm... after a bit more debugging i see its not an instance of Skeleton at all.

I'll try to look into this later this weekend and see, but I really apprechiate any help :)

Tanks again,

solo95 wrote Feb 7, 2014 at 10:00 AM

It seems that in CreateStringKeyDictionary: when it CreateGenericList it will use the parameters t1,t2 of which is the Dictionary<t1,t2> type - it looses the type information (in this case 2) - a fix would be check the type of the IList and use that type as the parameter?


solo95 wrote Feb 7, 2014 at 10:40 AM

I've managed to do a quick hack to create a list with type expected by adding:

val = CreateGenericList((List<object>)values.Value, GetTypeFromFirstClassInfo((List<object>)values.Value, globalTypes, t2), t1, globalTypes);
    private Type GetTypeFromFirstClassInfo(List<object> classInfos, Dictionary<string, object> globalTypes, Type defaultValue)
    if (null == classInfos || 0 == classInfos.Count)
      return defaultValue;

    return GetTypeFromClassInfo((Dictionary<string, object>)classInfos[0],globalTypes, defaultValue);

    private static Type GetTypeFromClassInfo(Dictionary<string, object> clz, Dictionary<string, object> globalTypes, Type defaulType)
    object typeInfo;
    if (!clz.TryGetValue("$type", out typeInfo))
      return defaulType;

    return Reflection.Instance.GetTypeFromCache((string)globalTypes[(string)typeInfo]);
And in CreateGenericList:
changed to IList col = (IList)Reflection.Instance.CreateGenericListInstance(pt);
  internal object CreateGenericListInstance(Type objType)
    var listType = typeof(List<>);
    var constructedListType = listType.MakeGenericType(objType);

    return Activator.CreateInstance(constructedListType);
That seems to work ok, however I stuck into a problem that I thought this deserializer could handle. The SkeletonPoint do not implement IConvertible and thus exception. However it's plain class (?) and the properties should be deserialized accordingly?

the json:
"Position": {
                "$type": "3",
                "X": 0.03670933,
                "Y": 0.4236084,
                "Z": 3.015385

Whereas the type 3 = Microsoft.Kinect.SkeletonPoint, Microsoft.Kinect

It seems to me extra ordinary to add custom serializer and deserializer for this type or again - am I doing something wrong? :)


solo95 wrote Feb 7, 2014 at 12:48 PM

Hi, I've just checked the code again and found:
Fixed that using a overload on ChangeType since a check is already done if it's a dict<str,obj> - I just replaced the ParseDictionary method (there are 11 references in the code to ChangeType. Is this correct assumption.

Stumbeled into a new problem - the setter is null when a property is internal set - is it feasable to use reflection is such case? (of course a slowdown)...
  private object ChangeType(object value, Type conversionType, Dictionary<string,object> globaltypes)
    var dict = value as Dictionary<string, object>;
    if (null == dict)
      return ChangeType(value, conversionType);

    return this.ParseDictionary(dict, globaltypes, conversionType, null /*createNew*/);

solo95 wrote Feb 7, 2014 at 1:03 PM

I've "fixed" that to allow on public properties to have internal setters - however it does not deserialize the e.g. jointscollection properly - i give up! :)

Thanks for the supprt!