public virtual object ReadJson(JsonReader reader, Type objectType)
 {
     throw new NotImplementedException(string.Format("{0} has not overriden FromJson method.", GetType().Name));
 }
        private object PopulateObject(JsonReader reader, Type objectType)
        {
            object newObject = Activator.CreateInstance(objectType);

              while (reader.Read())
              {
            switch (reader.TokenType)
            {
              case JsonToken.PropertyName:
            string memberName = reader.Value.ToString();

            SetObjectMember(reader, newObject, objectType, memberName);
            break;
              case JsonToken.EndObject:
            return newObject;
              default:
            throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType);
            }
              }

              throw new JsonSerializationException("Unexpected end when deserializing object.");
        }
        private void SetObjectMember(JsonReader reader, object target, Type targetType, string memberName)
        {
            if (!reader.Read())
            throw new JsonSerializationException(string.Format("Unexpected end when setting {0}'s value.", memberName));

              MemberMappingCollection memberMappings = GetMemberMappings(targetType);
              Type memberType;
              object value;

              // test if a member with memberName exists on the type
              // otherwise test if target is a dictionary and assign value with the key if it is
              if (memberMappings.Contains(memberName))
              {
            MemberMapping memberMapping = memberMappings[memberName];

            if (memberMapping.Ignored)
              return;

            // ignore member if it is readonly
            if (!memberMapping.Writable)
              return;

            // get the member's underlying type
            memberType = ReflectionUtils.GetMemberUnderlyingType(memberMapping.Member);

            value = GetObject(reader, memberType);

            if (_nullValueHandling == NullValueHandling.Ignore && value == null)
              return;

            ReflectionUtils.SetMemberValue(memberMapping.Member, target, value);
              }
              else if (typeof(IDictionary).IsAssignableFrom(targetType))
              {
            // attempt to get the IDictionary's type
            memberType = ReflectionUtils.GetDictionaryValueType(targetType);
            value = GetObject(reader, memberType);

            Type keyType = ReflectionUtils.GetDictionaryKeyType(targetType);
            object keyValue = EnsureType(memberName, keyType);

            ((IDictionary)target).Add(keyValue, value);
              }
              else
              {
            if (_missingMemberHandling == MissingMemberHandling.Error)
              throw new JsonSerializationException(string.Format("Could not find member '{0}' on object of type '{1}'", memberName, targetType.GetType().Name));
              }
        }
        private JavaScriptObject PopulateJavaScriptObject(JsonReader reader)
        {
            JavaScriptObject jsObject = new JavaScriptObject();

              while (reader.Read())
              {
            switch (reader.TokenType)
            {
              case JsonToken.PropertyName:
            string memberName = reader.Value.ToString();

            // move to the value token. skip comments
            do
            {
              if (!reader.Read())
                throw new JsonSerializationException("Unexpected end while deserializing object.");
            } while (reader.TokenType == JsonToken.Comment);

            object value = GetObject(reader, null);

            jsObject[memberName] = value;
            break;
              case JsonToken.EndObject:
            return jsObject;
              case JsonToken.Comment:
            break;
              default:
            throw new JsonSerializationException("Unexpected token while deserializing object: " + reader.TokenType);
            }
              }

              throw new JsonSerializationException("Unexpected end while deserializing object.");
        }
        private object PopulateList(JsonReader reader, Type objectType)
        {
            Type elementType = ReflectionUtils.GetListItemType(objectType);

              IList populatedList = CollectionUtils.CreateAndPopulateList(objectType, delegate(IList list)
            {
              while (reader.Read())
              {
            switch (reader.TokenType)
            {
              case JsonToken.EndArray:
                return;
              case JsonToken.Comment:
                break;
              default:
                object value = GetObject(reader, elementType);

                list.Add(value);
                break;
            }
              }

              throw new JsonSerializationException("Unexpected end when deserializing array.");
            });

              return populatedList;
        }
        private JavaScriptArray PopulateJavaScriptArray(JsonReader reader)
        {
            JavaScriptArray jsArray = new JavaScriptArray();

              while (reader.Read())
              {
            switch (reader.TokenType)
            {
              case JsonToken.EndArray:
            return jsArray;
              case JsonToken.Comment:
            break;
              default:
            object value = GetObject(reader, null);

            jsArray.Add(value);
            break;
            }
              }

              throw new JsonSerializationException("Unexpected end while deserializing array.");
        }
        private object GetObject(JsonReader reader, Type objectType)
        {
            _level++;

              object value;
              JsonConverter converter;

              if (HasMatchingConverter(objectType, out converter))
              {
            return converter.ReadJson(reader, objectType);
              }
              else
              {
            switch (reader.TokenType)
            {
              // populate a typed object or generic dictionary/array
              // depending upon whether an objectType was supplied
              case JsonToken.StartObject:
            value = (objectType != null) ? PopulateObject(reader, objectType) : PopulateJavaScriptObject(reader);
            break;
              case JsonToken.StartArray:
            value = (objectType != null) ? PopulateList(reader, objectType) : PopulateJavaScriptArray(reader);
            break;
              case JsonToken.Integer:
              case JsonToken.Float:
              case JsonToken.String:
              case JsonToken.Boolean:
              case JsonToken.Date:
            value = EnsureType(reader.Value, objectType);
            break;
              case JsonToken.StartConstructor:
              case JsonToken.EndConstructor:
            string constructorName = reader.Value.ToString();

            //if (string.CompareOrdinal(constructorName, "Date") == 0)
            //  value = CreateDate(reader);
            //else
              //TODO: use objectType plus constructor arguments to instantiate object
              value = constructorName;
            break;
              case JsonToken.Null:
              case JsonToken.Undefined:
            value = null;
            break;
              default:
            throw new JsonSerializationException("Unexpected token while deserializing object: " + reader.TokenType);
            }
              }

              _level--;

              return value;
        }
        private DateTime CreateDate(JsonReader reader)
        {
            // move to parameter
              if (!reader.Read())
            throw new JsonSerializationException("Unexpected end while creating date.");

              //TODO: add support for Date constructor with multiple arguments
              long ticks = Convert.ToInt64(reader.Value);
              DateTime date = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(ticks);

              // move to constructor end
              if (!reader.Read())
            throw new JsonSerializationException("Unexpected end while creating date.");
              if (reader.TokenType != JsonToken.EndConstructor)
            throw new JsonSerializationException("Unexpected token while creating date: " + reader.TokenType);

              return date;
        }
        /// <summary>
        /// Deserializes the Json structure contained by the specified <see cref="JsonReader"/>
        /// into an instance of the specified type.
        /// </summary>
        /// <param name="reader">The type of object to create.</param>
        /// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param>
        /// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
        public object Deserialize(JsonReader reader, Type objectType)
        {
            if (reader == null)
            throw new ArgumentNullException("reader");

              if (!reader.Read())
            return null;

              return GetObject(reader, objectType);
        }
 /// <summary>
 /// Deserializes the Json structure contained by the specified <see cref="JsonReader"/>.
 /// </summary>
 /// <param name="reader">The <see cref="JsonReader"/> that contains the Json structure to deserialize.</param>
 /// <returns>The <see cref="Object"/> being deserialized.</returns>
 public object Deserialize(JsonReader reader)
 {
     return Deserialize(reader, null);
 }