private JToken CreateJToken(JsonReader reader, JsonContract contract)
        {
            ValidationUtils.ArgumentNotNull(reader, nameof(reader));

            if (contract != null)
            {
                if (contract.UnderlyingType == typeof(JRaw))
                {
                    return JRaw.Create(reader);
                }
                if (reader.TokenType == JsonToken.Null
                    && !(contract.UnderlyingType == typeof(JValue) || contract.UnderlyingType == typeof(JToken)))
                {
                    return null;
                }
            }

            JToken token;
            using (JTokenWriter writer = new JTokenWriter())
            {
                writer.WriteToken(reader);
                token = writer.Token;
            }

            return token;
        }
        private JToken CreateJObject(JsonReader reader)
        {
            ValidationUtils.ArgumentNotNull(reader, nameof(reader));

            // this is needed because we've already read inside the object, looking for metadata properties
            using (JTokenWriter writer = new JTokenWriter())
            {
                writer.WriteStartObject();

                do
                {
                    if (reader.TokenType == JsonToken.PropertyName)
                    {
                        string propertyName = (string)reader.Value;
                        if (!reader.ReadAndMoveToContent())
                        {
                            break;
                        }

                        if (CheckPropertyName(reader, propertyName))
                        {
                            continue;
                        }

                        writer.WritePropertyName(propertyName);
                        writer.WriteToken(reader, true, true, false);
                    }
                    else if (reader.TokenType == JsonToken.Comment)
                    {
                        // eat
                    }
                    else
                    {
                        writer.WriteEndObject();
                        return writer.Token;
                    }
                } while (reader.Read());

                throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
            }
        }