private static object CoerceType(Type targetType, object value, int index, bool allowNullValueTypes) { bool isNullable = JsonReader.IsNullable(targetType); if (value == null) { if (allowNullValueTypes && targetType.IsValueType && !isNullable) { throw new JsonDeserializationException(String.Format(JsonReader.ErrorNullValueType, targetType.FullName), index); } return(value); } if (isNullable) { // nullable types have a real underlying struct Type[] genericArgs = targetType.GetGenericArguments(); if (genericArgs.Length == 1) { targetType = genericArgs[0]; } } Type actualType = value.GetType(); if (targetType.IsAssignableFrom(actualType)) { return(value); } if (targetType.IsEnum) { if (!Enum.IsDefined(targetType, value)) { // if isn't a defined value perhaps it is the JsonName foreach (FieldInfo field in targetType.GetFields()) { string jsonName = JsonNameAttribute.GetJsonName(field); if (((string)value).Equals(jsonName)) { value = field.Name; break; } } } if (value is String) { return(Enum.Parse(targetType, (string)value)); } else { return(Convert.ChangeType(value, targetType)); } } if (actualType.IsArray && !targetType.IsArray) { return(JsonReader.CoerceArray(targetType, actualType, value, index, allowNullValueTypes)); } if (value is String) { if (targetType == typeof(DateTime)) { DateTime date; if (DateTime.TryParse( (string)value, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.RoundtripKind | DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault, out date)) { return(date); } } else if (targetType == typeof(Guid)) { // try-catch is pointless since will throw upon generic conversion return(new Guid((string)value)); } else if (targetType == typeof(Uri)) { Uri uri; if (Uri.TryCreate((string)value, UriKind.RelativeOrAbsolute, out uri)) { return(uri); } } else if (targetType == typeof(Version)) { // try-catch is pointless since will throw upon generic conversion return(new Version((string)value)); } } else if (targetType == typeof(TimeSpan)) { return(new TimeSpan((long)JsonReader.CoerceType(typeof(Int64), value, index, allowNullValueTypes))); } TypeConverter converter = TypeDescriptor.GetConverter(targetType); if (converter.CanConvertFrom(actualType)) { return(converter.ConvertFrom(value)); } converter = TypeDescriptor.GetConverter(actualType); if (converter.CanConvertTo(targetType)) { return(converter.ConvertTo(value, targetType)); } return(Convert.ChangeType(value, targetType)); }