private object PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
        {
            var wrappedCollection = list as IWrappedCollection;
            var 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);

            var initialDepth = reader.Depth;

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

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

            int? previousErrorIndex = null;

            var 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)
                {
                    var 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);
                        }
                        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;
                var list = contract.CreateTemporaryCollection();

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

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

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

                createdFromNonDefaultCreator = false;
                return (IList)list;
            }
            if (contract.HasParametrizedCreator)
            {
                createdFromNonDefaultCreator = true;
                return contract.CreateTemporaryCollection();
            }
            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 void PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
        {
            var rank = contract.UnderlyingType.GetArrayRank();

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

            OnDeserializing(reader, contract, list);

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

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

            var finished = false;
            do
            {
                var 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)
                    {
                        var 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);
                            }
                            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);
        }
        private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
        {
            var isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays);
            // don't make readonly fields the referenced value because they can't be deserialized to
            isReference = (isReference && (member == null || member.Writable));

            var includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
            var 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)
        {
            var dimension = indices.Length;
            var newIndices = new int[dimension + 1];
            for (var i = 0; i < dimension; i++)
            {
                newIndices[i] = indices[i];
            }

            writer.WriteStartArray();

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

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

                    try
                    {
                        var 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);

            var 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)
        {
            var wrappedCollection = values as IWrappedCollection;
            var underlyingList = wrappedCollection != null ? wrappedCollection.UnderlyingCollection : values;

            OnSerializing(writer, contract, underlyingList);

            _serializeStack.Add(underlyingList);

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

            writer.WriteStartArray();

            var initialDepth = writer.Top;

            var index = 0;
            // note that an error in the IEnumerable won't be caught
            foreach (var value in values)
            {
                try
                {
                    var 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);
        }