private object PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
    {
      int rank = contract.UnderlyingType.GetArrayRank();

      if (id != null)
        Serializer.ReferenceResolver.AddReference(this, id, list);

      contract.InvokeOnDeserializing(list, Serializer.Context);

      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 = collectionItemConverter.ReadJson(reader, contract.CollectionItemType, null, GetInternalSerializer());
                  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.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.");

      contract.InvokeOnDeserialized(list, Serializer.Context);
      return list;
    }
    private object PopulateList(IWrappedCollection wrappedList, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
    {
      object list = wrappedList.UnderlyingCollection;

      if (id != null)
        Serializer.ReferenceResolver.AddReference(this, id, list);

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

      contract.InvokeOnDeserializing(list, Serializer.Context);

      int initialDepth = reader.Depth;

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

      int? previousErrorIndex = null;

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

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

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

          if (IsErrorHandled(list, contract, errorPosition.Position, 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, list, "Unexpected end when deserializing array.");

      contract.InvokeOnDeserialized(list, Serializer.Context);
      return list;
    }