private object PopulateList (IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
		{
			IWrappedCollection wrappedCollection = list as IWrappedCollection;
			object underlyingList = wrappedCollection != null ? wrappedCollection.UnderlyingCollection : list;

			if (id != null)
				AddReference(reader, id, underlyingList);

			// can't populate an existing array
			if (list.IsFixedSize) {
				reader.Skip();
				return underlyingList;
			}

			OnDeserializing(reader, contract, underlyingList);

			int initialDepth = reader.Depth;

			if (contract.ItemContract == null)
				contract.ItemContract = GetContractSafe(contract.CollectionItemType);

			JsonConverter collectionItemConverter = GetConverter(contract.ItemContract, null, contract, containerProperty);

			int? previousErrorIndex = null;

			bool finished = false;
			do {
				try {
					if (ReadForType(reader, contract.ItemContract, collectionItemConverter != null)) {
						switch (reader.TokenType) {
						case JsonToken.EndArray:
							finished = true;
							break;
						case JsonToken.Comment:
							break;
						default:
							object value;

							if (collectionItemConverter != null && collectionItemConverter.CanRead)
								value = DeserializeConvertable(collectionItemConverter, reader, contract.CollectionItemType, null);
							else
								value = CreateValueInternal(reader, contract.CollectionItemType, contract.ItemContract, null, contract, containerProperty, null);

							list.Add(value);
							break;
						}
					}
					else {
						break;
					}
				}
				catch (Exception ex) {
					JsonPosition errorPosition = reader.GetPosition(initialDepth);

					if (IsErrorHandled(underlyingList, contract, errorPosition.Position, reader as IJsonLineInfo, reader.Path, ex)) {
						HandleError(reader, true, initialDepth);

						if (previousErrorIndex != null && previousErrorIndex == errorPosition.Position) {
							// reader index has not moved since previous error handling
							// break out of reading array to prevent infinite loop
							throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex);
						}
						else {
							previousErrorIndex = errorPosition.Position;
						}
					}
					else {
						throw;
					}
				}
			} while (!finished);

			if (!finished)
				ThrowUnexpectedEndException(reader, contract, underlyingList, "Unexpected end when deserializing array.");

			OnDeserialized(reader, contract, underlyingList);
			return underlyingList;
		}
		private IList CreateNewList (JsonReader reader, JsonArrayContract contract, out bool createdFromNonDefaultCreator)
		{
			// some types like non-generic IEnumerable can be serialized but not deserialized
			if (!contract.CanDeserialize)
				throw JsonSerializationException.Create(reader, "Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType));

			if (contract.IsReadOnlyOrFixedSize) {
				createdFromNonDefaultCreator = true;
				IList list = contract.CreateTemporaryCollection();

				if (contract.ShouldCreateWrapper)
					list = contract.CreateWrapper(list);

				return list;
			}
			else if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) {
				object list = contract.DefaultCreator();

				if (contract.ShouldCreateWrapper)
					list = contract.CreateWrapper(list);

				createdFromNonDefaultCreator = false;
				return (IList)list;
			}
			else if (contract.HasParametrizedCreator) {
				createdFromNonDefaultCreator = true;
				return contract.CreateTemporaryCollection();
			}
			else {
				if (!contract.IsInstantiable)
					throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));

				throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
			}
		}
		private object PopulateMultidimensionalArray (IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
		{
			int rank = contract.UnderlyingType.GetArrayRank();

			if (id != null)
				AddReference(reader, id, list);

			OnDeserializing(reader, contract, list);

			JsonContract collectionItemContract = GetContractSafe(contract.CollectionItemType);
			JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty);

			int? previousErrorIndex = null;
			Stack<IList> listStack = new Stack<IList>();
			listStack.Push(list);
			IList currentList = list;

			bool finished = false;
			do {
				int initialDepth = reader.Depth;

				if (listStack.Count == rank) {
					try {
						if (ReadForType(reader, collectionItemContract, collectionItemConverter != null)) {
							switch (reader.TokenType) {
							case JsonToken.EndArray:
								listStack.Pop();
								currentList = listStack.Peek();
								previousErrorIndex = null;
								break;
							case JsonToken.Comment:
								break;
							default:
								object value;

								if (collectionItemConverter != null && collectionItemConverter.CanRead)
									value = DeserializeConvertable(collectionItemConverter, reader, contract.CollectionItemType, null);
								else
									value = CreateValueInternal(reader, contract.CollectionItemType, collectionItemContract, null, contract, containerProperty, null);

								currentList.Add(value);
								break;
							}
						}
						else {
							break;
						}
					}
					catch (Exception ex) {
						JsonPosition errorPosition = reader.GetPosition(initialDepth);

						if (IsErrorHandled(list, contract, errorPosition.Position, reader as IJsonLineInfo, reader.Path, ex)) {
							HandleError(reader, true, initialDepth);

							if (previousErrorIndex != null && previousErrorIndex == errorPosition.Position) {
								// reader index has not moved since previous error handling
								// break out of reading array to prevent infinite loop
								throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex);
							}
							else {
								previousErrorIndex = errorPosition.Position;
							}
						}
						else {
							throw;
						}
					}
				}
				else {
					if (reader.Read()) {
						switch (reader.TokenType) {
						case JsonToken.StartArray:
							IList newList = new List<object>();
							currentList.Add(newList);
							listStack.Push(newList);
							currentList = newList;
							break;
						case JsonToken.EndArray:
							listStack.Pop();

							if (listStack.Count > 0) {
								currentList = listStack.Peek();
							}
							else {
								finished = true;
							}
							break;
						case JsonToken.Comment:
							break;
						default:
							throw JsonSerializationException.Create(reader, "Unexpected token when deserializing multidimensional array: " + reader.TokenType);
						}
					}
					else {
						break;
					}
				}
			} while (!finished);

			if (!finished)
				ThrowUnexpectedEndException(reader, contract, list, "Unexpected end when deserializing array.");

			OnDeserialized(reader, contract, list);
			return list;
		}
        private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
        {
            bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays);
            bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
            bool writeMetadataObject = isReference || includeTypeDetails;

            if (writeMetadataObject)
            {
                writer.WriteStartObject();

                if (isReference)
                {
                    WriteReferenceIdProperty(writer, contract.UnderlyingType, values);
                }
                if (includeTypeDetails)
                {
                    WriteTypeProperty(writer, values.GetType());
                }
                writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName, false);
            }

            if (contract.ItemContract == null)
                contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object));

            return writeMetadataObject;
        }
        private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, int initialDepth, int[] indices)
        {
            int dimension = indices.Length;
            int[] newIndices = new int[dimension + 1];
            for (int i = 0; i < dimension; i++)
            {
                newIndices[i] = indices[i];
            }

            writer.WriteStartArray();

            for (int i = 0; i < values.GetLength(dimension); i++)
            {
                newIndices[dimension] = i;
                bool isTopLevel = (newIndices.Length == values.Rank);

                if (isTopLevel)
                {
                    object value = values.GetValue(newIndices);

                    try
                    {
                        JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);

                        if (ShouldWriteReference(value, null, valueContract, contract, member))
                        {
                            WriteReference(writer, value);
                        }
                        else
                        {
                            if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
                            {
                                SerializeValue(writer, value, valueContract, null, contract, member);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        if (IsErrorHandled(values, contract, i, null, writer.ContainerPath, ex))
                            HandleError(writer, initialDepth + 1);
                        else
                            throw;
                    }
                }
                else
                {
                    SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, newIndices);
                }
            }

            writer.WriteEndArray();
        }
        private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            OnSerializing(writer, contract, values);

            _serializeStack.Add(values);

            bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty);

            SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]);

            if (hasWrittenMetadataObject)
                writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, values);
        }
        private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            IWrappedCollection wrappedCollection = values as IWrappedCollection;
            object underlyingList = wrappedCollection != null ? wrappedCollection.UnderlyingCollection : values;

            OnSerializing(writer, contract, underlyingList);

            _serializeStack.Add(underlyingList);

            bool hasWrittenMetadataObject = WriteStartArray(writer, underlyingList, contract, member, collectionContract, containerProperty);

            writer.WriteStartArray();

            int initialDepth = writer.Top;

            int index = 0;
            // note that an error in the IEnumerable won't be caught
            foreach (object value in values)
            {
                try
                {
                    JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);

                    if (ShouldWriteReference(value, null, valueContract, contract, member))
                    {
                        WriteReference(writer, value);
                    }
                    else
                    {
                        if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
                        {
                            SerializeValue(writer, value, valueContract, null, contract, member);
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (IsErrorHandled(underlyingList, contract, index, null, writer.ContainerPath, ex))
                        HandleError(writer, initialDepth);
                    else
                        throw;
                }
                finally
                {
                    index++;
                }
            }

            writer.WriteEndArray();

            if (hasWrittenMetadataObject)
                writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, underlyingList);
        }