/// <summary>
        /// Deserialize the given JSON value according to the specified CLR type.
        /// </summary>
        /// <param name="type">The CLR type to deserialize the JSON value to.</param>
        /// <param name="jsonValue">The JSON value to deserialize.</param>
        /// <returns>The CLR object that the JSON value was deserialized from.</returns>
        public object DeserializeValue(Type type, JsonValue jsonValue)
        {
            if (ReferenceEquals(jsonValue, JsonNull.Instance))
            {
                return null;
            }

            var converter = JsonConverterFactory.CreateInstance(type);

            return converter.DeserializeValue(this, type, jsonValue);
        }
        /// <summary>
        /// Deserialize a JSON value to a defined CLR type.
        /// </summary>
        /// <param name="serializer">The serializer to utilize when deserializing nested objects.</param>
        /// <param name="type">The CLR type to deserialize the JSON value to.</param>
        /// <param name="jsonValue">The JSON value to deserialize.</param>
        /// <returns>The object that represents the CLR version of the given JSON value.</returns>
        public object DeserializeValue(IJsonSerializer serializer, Type type, JsonValue jsonValue)
        {
            var jsonArray = (JsonArray) jsonValue;

            if (type.IsArray)
            {
                return DeserializeArray(serializer, type, jsonArray);
            }

            if (TypeHelper.IsCollection(type))
            {
                return DeserializeCollection(serializer, type, jsonArray);
            }

            if (type.GetTypeInfo().IsGenericType && type.GetTypeInfo().GetGenericTypeDefinition() == typeof(IReadOnlyList<>))
            {
                type = typeof(List<>).MakeGenericType(type.GenericTypeArguments[0]);

                return DeserializeValue(serializer, type, jsonArray);
            }

            throw new NotSupportedException();
        }
        /// <summary>
        /// Read an object from the given JSON value.
        /// </summary>
        /// <param name="type">The type of the object to deserialize.</param>
        /// <param name="jsonValue">The JSON value to read.</param>
        /// <returns>The object that was read.</returns>
        protected virtual object ReadFromJsonValue(Type type, JsonValue jsonValue)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IPatch<>))
            {
                return CreatePatch(type, ContractResolver, jsonValue);
            }

            return DeserializeValue(type, jsonValue);
        }
        /// <summary>
        /// Deserialize an object.
        /// </summary>
        /// <param name="type">The type of the object to deserialize.</param>
        /// <param name="jsonValue">The JSON value that represents the object to deserialize.</param>
        protected virtual object DeserializeValue(Type type, JsonValue jsonValue)
        {
            var serializer = new JsonSerializer(new JsonConverterFactory(new ContractConverter(ContractResolver)), new DefaultFieldNamingStrategy());

            return serializer.DeserializeValue(type, jsonValue);
        }
        /// <summary>
        /// Creates an instance of the patch object for the media type.
        /// </summary>
        /// <param name="type">The type of the inner instance that is being patched.</param>
        /// <param name="contractResolver">The contract resolver.</param>
        /// <param name="jsonValue">The JSON value that represents the patch values.</param>
        /// <returns>The instance of the patch.</returns>
        protected virtual IPatch CreatePatch(Type type, IContractResolver contractResolver, JsonValue jsonValue)
        {
            var patch = typeof(JsonPatch<>).MakeGenericType(type.GenericTypeArguments[0]);

            var constructor = patch.GetConstructor(new[] { typeof(IContractResolver), typeof(JsonObject) });
            Debug.Assert(constructor != null);

            return (IPatch)constructor.Invoke(new object[] { ContractResolver, jsonValue });
        }
        /// <summary>
        /// Deserialize a JSON value to a defined CLR type.
        /// </summary>
        /// <param name="serializer">The serializer to utilize when deserializing nested objects.</param>
        /// <param name="type">The CLR type to deserialize the JSON value to.</param>
        /// <param name="jsonValue">The JSON value to deserialize.</param>
        /// <returns>The object that represents the CLR version of the given JSON value.</returns>
        public object DeserializeValue(IJsonSerializer serializer, Type type, JsonValue jsonValue)
        {
            var text = ((JsonString)jsonValue).Value;

            return Enum.Parse(type, text, true);
        }
        /// <summary>
        /// Deserialize a JSON value to a defined CLR type.
        /// </summary>
        /// <param name="serializer">The serializer to utilize when deserializing nested objects.</param>
        /// <param name="type">The CLR type to deserialize the JSON value to.</param>
        /// <param name="jsonValue">The JSON value to deserialize.</param>
        /// <returns>The object that represents the CLR version of the given JSON value.</returns>
        public object DeserializeValue(IJsonSerializer serializer, Type type, JsonValue jsonValue)
        {
            if (type == typeof(string))
            {
                return ((JsonString)jsonValue).Value;
            }

            if (type == typeof(Guid))
            {
                return new Guid(((JsonString)jsonValue).Value);
            }

            if (type == typeof(short))
            {
                return (short)((JsonNumber)jsonValue).Value;
            }

            if (type == typeof(ushort))
            {
                return (ushort)((JsonNumber)jsonValue).Value;
            }

            if (type == typeof(int))
            {
                return (int)((JsonNumber)jsonValue).Value;
            }

            if (type == typeof(long))
            {
                return (long)((JsonNumber)jsonValue).Value;
            }

            if (type == typeof(decimal))
            {
                return ((JsonNumber)jsonValue).Value;
            }

            if (type == typeof(float))
            {
                return (float)((JsonNumber)jsonValue).Value;
            }

            if (type == typeof(double))
            {
                return (double)((JsonNumber)jsonValue).Value;
            }

            if (type == typeof(DateTime))
            {
                return DateTime.Parse(((JsonString)jsonValue).Value);
            }

            if (type == typeof(DateTimeOffset))
            {
                return DateTimeOffset.Parse(((JsonString)jsonValue).Value);
            }

            if (type == typeof(bool))
            {
                return ((JsonBoolean)jsonValue).Value;
            }

            throw new NotSupportedException(type.ToString());
        }
        /// <summary>
        /// Deserialize a JSON value to a defined CLR type.
        /// </summary>
        /// <param name="serializer">The serializer to utilize when deserializing nested objects.</param>
        /// <param name="type">The CLR type to deserialize the JSON value to.</param>
        /// <param name="jsonValue">The JSON value to deserialize.</param>
        /// <returns>The object that represents the CLR version of the given JSON value.</returns>
        public object DeserializeValue(IJsonSerializer serializer, Type type, JsonValue jsonValue)
        {
            type = Nullable.GetUnderlyingType(type) ?? type;

            return serializer.DeserializeValue(type, jsonValue);
        }
 /// <summary>
 /// Deserialize the given JSON value according to the specified CLR type.
 /// </summary>
 /// <param name="type">The CLR type to deserialize the JSON value to.</param>
 /// <param name="jsonValue">The JSON value to deserialize.</param>
 /// <returns>The CLR object that the JSON value was deserialized from.</returns>
 object IJsonSerializer.DeserializeValue(Type type, JsonValue jsonValue)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Deserialize a JSON value to a defined CLR type.
 /// </summary>
 /// <param name="serializer">The serializer to utilize when deserializing nested objects.</param>
 /// <param name="type">The CLR type to deserialize the JSON value to.</param>
 /// <param name="jsonValue">The JSON value to deserialize.</param>
 /// <returns>The object that represents the CLR version of the given JSON value.</returns>
 public object DeserializeValue(IJsonSerializer serializer, Type type, JsonValue jsonValue)
 {
     return DeserializeObject(serializer, type, (JsonObject)jsonValue);
 }
        /// <summary>
        /// Deserialize a JSON object.
        /// </summary>
        /// <param name="serializer">The serializer to utilize when deserializing nested objects.</param>
        /// <param name="type">The type of the object to deserialize to.</param>
        /// <param name="jsonValue">The JSON value to deserialize from.</param>
        /// <returns>The CLR object that represents the JSON object.</returns>
        object DeserializeObject(IJsonSerializer serializer, Type type, JsonValue jsonValue)
        {
            IContract contract;
            if (_contractResolver.TryResolve(type, out contract) == false)
            {
                throw new HypermediaWebApiException($"Could not resolve a contract for {type}.");
            }

            var instance = Activator.CreateInstance(type);

            DeserializeObject(serializer, (JsonObject)jsonValue, contract, instance);

            return instance;
        }
        /// <summary>
        /// Deserialize an object.
        /// </summary>
        /// <param name="type">The type of the object to deserialize.</param>
        /// <param name="jsonValue">The JSON value that represents the object to deserialize.</param>
        protected override object DeserializeValue(Type type, JsonValue jsonValue)
        {
            var jsonObject = jsonValue as JsonObject;

            if (jsonObject == null)
            {
                throw new HypermediaWebApiException("The top level JSON value must be an Object.");
            }

            var serializer = new JsonApiSerializer(ContractResolver, _fieldNamingStratgey);

            if (TypeHelper.IsEnumerable(type))
            {
                return serializer.DeserializeMany(jsonObject);
            }

            return serializer.DeserializeEntity(jsonObject);
        }