private object ReadValue(JsonSerializer serializer, JsonReader reader)
    {
        while (reader.TokenType == JsonToken.Comment)
        {
            if (!reader.Read())
            {
                throw JsonSerializationExceptionExtensions.Create(reader, "Unexpected end when reading ExpandoObject.");
            }
        }
        switch (reader.TokenType)
        {
        case JsonToken.StartObject:
            return(ReadObject(serializer, reader));

        case JsonToken.StartArray:
            return(ReadList(serializer, reader));

        default:
            if (JsonTokenUtils.IsPrimitiveToken(reader.TokenType))
            {
                return(reader.Value);
            }
            throw JsonSerializationExceptionExtensions.Create(reader, "Unexpected token when converting ExpandoObject");
        }
    }
    private object ReadObject(JsonSerializer serializer, JsonReader reader)
    {
        IDictionary <string, object> expandoObject = null;
        object referenceObject = null;

        while (reader.Read())
        {
            switch (reader.TokenType)
            {
            case JsonToken.PropertyName:
                string propertyName = reader.Value.ToString();
                if (!reader.Read())
                {
                    throw new InvalidOperationException("Unexpected end when reading ExpandoObject.");
                }
                object v = ReadValue(serializer, reader);
                if (propertyName == "$ref")
                {
                    var id = (v == null ? null : Convert.ToString(v, CultureInfo.InvariantCulture));
                    referenceObject = serializer.ReferenceResolver.ResolveReference(serializer, id);
                }
                else if (propertyName == "$id")
                {
                    var id = (v == null ? null : Convert.ToString(v, CultureInfo.InvariantCulture));
                    serializer.ReferenceResolver.AddReference(serializer, id, (expandoObject ?? (expandoObject = new ExpandoObject())));
                }
                else
                {
                    (expandoObject ?? (expandoObject = new ExpandoObject()))[propertyName] = v;
                }
                break;

            case JsonToken.Comment:
                break;

            case JsonToken.EndObject:
                if (referenceObject != null && expandoObject != null)
                {
                    throw JsonSerializationExceptionExtensions.Create(reader, "ExpandoObject contained both $ref and real data");
                }
                return(referenceObject ?? expandoObject);
            }
        }
        throw JsonSerializationExceptionExtensions.Create(reader, "Unexpected end when reading ExpandoObject.");
    }
    private object ReadList(JsonSerializer serializer, JsonReader reader)
    {
        IList <object> list = new List <object>();

        while (reader.Read())
        {
            switch (reader.TokenType)
            {
            case JsonToken.Comment:
                break;

            default:
                object v = ReadValue(serializer, reader);
                list.Add(v);
                break;

            case JsonToken.EndArray:
                return(list);
            }
        }
        throw JsonSerializationExceptionExtensions.Create(reader, "Unexpected end when reading ExpandoObject.");
    }