Ejemplo n.º 1
0
        private object CoerceType(Type targetType, IDictionary value, out Dictionary <string, MemberInfo> memberMap)
        {
            object newValue = this.InstantiateObject(targetType, out memberMap);

            if (memberMap != null)
            {
                // copy any values into new object
                foreach (object key in value.Keys)
                {
                    MemberInfo memberInfo;
                    Type       memberType = TypeCoercionUtility.GetMemberInfo(memberMap, key as String, out memberInfo);
                    this.SetMemberValue(newValue, memberType, memberInfo, value[key]);
                }
            }
            return(newValue);
        }
Ejemplo n.º 2
0
        public static bool IsJsonIgnore(object value)
        {
            if (value == null)
            {
                return(false);
            }
            Type type = value.GetType();
            ICustomAttributeProvider customAttributeProvider;

            if (TypeCoercionUtility.GetTypeInfo(type).IsEnum)
            {
                customAttributeProvider = TypeCoercionUtility.GetTypeInfo(type).GetField(Enum.GetName(type, value));
            }
            else
            {
                customAttributeProvider = (value as ICustomAttributeProvider);
            }
            if (customAttributeProvider == null)
            {
                throw new ArgumentException();
            }
            return(customAttributeProvider.IsDefined(typeof(JsonIgnoreAttribute), true));
        }
Ejemplo n.º 3
0
        private Type GetGenericDictionaryType(Type objectType)
        {
            Type @interface = TypeCoercionUtility.GetTypeInfo(objectType).GetInterface(JsonReader.TypeGenericIDictionary);

            if (@interface != null)
            {
                Type[] genericArguments = @interface.GetGenericArguments();
                if (genericArguments.Length == 2)
                {
                    if (!object.Equals(genericArguments[0], typeof(string)))
                    {
                        throw new JsonDeserializationException(string.Format("Types which implement Generic IDictionary<TKey, TValue> need to have string keys to be deserialized. ({0})", new object[]
                        {
                            objectType
                        }), this.index);
                    }
                    if (!object.Equals(genericArguments[1], typeof(object)))
                    {
                        return(genericArguments[1]);
                    }
                }
            }
            return(null);
        }
Ejemplo n.º 4
0
        private void PopulateObject(ref object result, Type objectType, Dictionary <string, MemberInfo> memberMap, Type genericDictionaryType)
        {
            if (this.Source[this.index] != '{')
            {
                throw new JsonDeserializationException("Expected JSON object.", this.index);
            }
            IDictionary dictionary = result as IDictionary;

            if (dictionary == null && objectType.GetInterface(JsonReader.TypeGenericIDictionary) != null)
            {
                throw new JsonDeserializationException(string.Format("Types which implement Generic IDictionary<TKey, TValue> also need to implement IDictionary to be deserialized. ({0})", objectType), this.index);
            }
            JsonToken jsonToken;

            while (true)
            {
                this.index++;
                if (this.index >= this.SourceLength)
                {
                    break;
                }
                jsonToken = this.Tokenize(this.Settings.AllowUnquotedObjectKeys);
                if (jsonToken == JsonToken.ObjectEnd)
                {
                    goto Block_5;
                }
                if (jsonToken != JsonToken.String && jsonToken != JsonToken.UnquotedName)
                {
                    goto Block_7;
                }
                string     text = (jsonToken != JsonToken.String) ? this.ReadUnquotedKey() : ((string)this.ReadString(null));
                MemberInfo memberInfo;
                Type       type;
                if (genericDictionaryType == null && memberMap != null)
                {
                    type = TypeCoercionUtility.GetMemberInfo(memberMap, text, out memberInfo);
                }
                else
                {
                    type       = genericDictionaryType;
                    memberInfo = null;
                }
                jsonToken = this.Tokenize();
                if (jsonToken != JsonToken.NameDelim)
                {
                    goto Block_11;
                }
                this.index++;
                if (this.index >= this.SourceLength)
                {
                    goto Block_12;
                }
                if (this.Settings.HandleCyclicReferences && text == "@ref")
                {
                    int num = (int)this.Read(typeof(int), false);
                    result    = this.previouslyDeserialized[num];
                    jsonToken = this.Tokenize();
                }
                else
                {
                    object obj = this.Read(type, false);
                    if (dictionary != null)
                    {
                        if (objectType == null && this.Settings.IsTypeHintName(text))
                        {
                            result = this.Settings.Coercion.ProcessTypeHint(dictionary, obj as string, out objectType, out memberMap);
                        }
                        else
                        {
                            dictionary[text] = obj;
                        }
                    }
                    else
                    {
                        this.Settings.Coercion.SetMemberValue(result, type, memberInfo, obj);
                    }
                    jsonToken = this.Tokenize();
                }
                if (jsonToken != JsonToken.ValueDelim)
                {
                    goto IL_234;
                }
            }
            throw new JsonDeserializationException("Unterminated JSON object.", this.index);
Block_5:
            goto IL_234;
Block_7:
            throw new JsonDeserializationException("Expected JSON object property name.", this.index);
Block_11:
            throw new JsonDeserializationException("Expected JSON object property name delimiter.", this.index);
Block_12:
            throw new JsonDeserializationException("Unterminated JSON object.", this.index);
IL_234:
            if (jsonToken != JsonToken.ObjectEnd)
            {
                throw new JsonDeserializationException("Unterminated JSON object.", this.index);
            }
            this.index++;
        }
Ejemplo n.º 5
0
        private void PopulateObject(ref object result, Type objectType, Dictionary <string, MemberInfo> memberMap, Type genericDictionaryType)
        {
            if (this.Source[this.index] != JsonReader.OperatorObjectStart)
            {
                throw new JsonDeserializationException(JsonReader.ErrorExpectedObject, this.index);
            }

#if WINDOWS_PHONE
            IDictionary idict = result as IDictionary;
#else
            IDictionary idict = result as IDictionary;

            if (idict == null && objectType.GetInterface(JsonReader.TypeGenericIDictionary) != null)
            {
                throw new JsonDeserializationException(
                          String.Format(JsonReader.ErrorGenericIDictionary, objectType),
                          this.index);
            }
#endif

            JsonToken token;
            do
            {
                Type       memberType;
                MemberInfo memberInfo;

                // consume opening brace or delim
                this.index++;
                if (this.index >= this.SourceLength)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorUnterminatedObject, this.index);
                }

                // get next token
                token = this.Tokenize(this.Settings.AllowUnquotedObjectKeys);
                if (token == JsonToken.ObjectEnd)
                {
                    break;
                }

                if (token != JsonToken.String && token != JsonToken.UnquotedName)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorExpectedPropertyName, this.index);
                }

                // parse object member value
                string memberName = (token == JsonToken.String) ?
                                    (String)this.ReadString(null) :
                                    this.ReadUnquotedKey();

                //
                if (genericDictionaryType == null && memberMap != null)
                {
                    // determine the type of the property/field
                    memberType = TypeCoercionUtility.GetMemberInfo(memberMap, memberName, out memberInfo);
                }
                else
                {
                    memberType = genericDictionaryType;
                    memberInfo = null;
                }

                // get next token
                token = this.Tokenize();
                if (token != JsonToken.NameDelim)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorExpectedPropertyNameDelim, this.index);
                }

                // consume delim
                this.index++;
                if (this.index >= this.SourceLength)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorUnterminatedObject, this.index);
                }

                object value;

                // Reference to previously deserialized value
                if (Settings.HandleCyclicReferences && memberName == "@ref")
                {
                    // parse object member value
                    int refId = (int)this.Read(typeof(int), false);

                    // Change result object to the one previously deserialized
                    result = previouslyDeserialized[refId];

                    // get next token
                    // this will probably be the end of the object
                    token = this.Tokenize();
                    continue;
                }
                else
                {
                    // Normal serialized value

                    // parse object member value
                    value = this.Read(memberType, false);
                }

                if (idict != null)
                {
                    if (objectType == null && this.Settings.IsTypeHintName(memberName))
                    {
                        result = this.Settings.Coercion.ProcessTypeHint(idict, value as string, out objectType, out memberMap);
                    }
                    else
                    {
                        idict[memberName] = value;
                    }
                }
                else
                {
                    this.Settings.Coercion.SetMemberValue(result, memberType, memberInfo, value);
                }

                // get next token
                token = this.Tokenize();
            } while (token == JsonToken.ValueDelim);

            if (token != JsonToken.ObjectEnd)
            {
                throw new JsonDeserializationException(JsonReader.ErrorUnterminatedObject, this.index);
            }

            // consume closing brace
            this.index++;

            //return result;
        }
        internal object CoerceType(Type targetType, object value)
        {
            bool isNullable = TypeCoercionUtility.IsNullable(targetType);

            if (value == null)
            {
#if NETFX_CORE
                if (!allowNullValueTypes &&
                    targetType.IsValueType() &&
                    !isNullable)
#else
                if (!allowNullValueTypes &&
                    targetType.IsValueType &&
                    !isNullable)
#endif
                {
                    throw new JsonTypeCoercionException(String.Format(TypeCoercionUtility.ErrorNullValueType, targetType.FullName));
                }
                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 NETFX_CORE
            if (targetType.IsEnum())
#else
            if (targetType.IsEnum)
#endif
            {
                if (value is String)
                {
                    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;
                            }
                        }
                    }

                    return(Enum.Parse(targetType, (string)value));
                }
                else
                {
                    value = this.CoerceType(Enum.GetUnderlyingType(targetType), value);
                    return(Enum.ToObject(targetType, value));
                }
            }

            if (value is IDictionary)
            {
                Dictionary <string, MemberInfo> memberMap;
                return(this.CoerceType(targetType, (IDictionary)value, out memberMap));
            }

            if (typeof(IEnumerable).IsAssignableFrom(targetType) &&
                typeof(IEnumerable).IsAssignableFrom(actualType))
            {
                return(this.CoerceList(targetType, actualType, (IEnumerable)value));
            }

            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(Char))
                {
                    if (((string)value).Length == 1)
                    {
                        return(((string)value)[0]);
                    }
                }
                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)this.CoerceType(typeof(Int64), value)));
            }

#if !WINDOWS_PHONE && !NETFX_CORE
            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));
            }
#endif

            try
            {
                // fall back to basics
                return(Convert.ChangeType(value, targetType));
            }
            catch (Exception ex)
            {
                throw new JsonTypeCoercionException(
                          String.Format("Error converting {0} to {1}", value.GetType().FullName, targetType.FullName), ex);
            }
        }
Ejemplo n.º 7
0
        private IEnumerable ReadArray(Type arrayType)
        {
            if (this.Source[this.index] != '[')
            {
                throw new JsonDeserializationException("Expected JSON array.", this.index);
            }
            bool flag       = !object.Equals(arrayType, null);
            bool typeIsHint = !flag;
            Type type       = null;

            if (flag)
            {
                if (arrayType.HasElementType)
                {
                    type = arrayType.GetElementType();
                }
                else if (TypeCoercionUtility.GetTypeInfo(arrayType).IsGenericType)
                {
                    Type[] genericArguments = arrayType.GetGenericArguments();
                    if (genericArguments.Length == 1)
                    {
                        type = genericArguments[0];
                    }
                }
            }
            List <object> list = (this.jsArrays.Count <= 0) ? new List <object>() : this.jsArrays.Pop();

            list.Clear();
            JsonToken jsonToken;

            for (;;)
            {
                this.index++;
                if (this.index >= this.SourceLength)
                {
                    break;
                }
                jsonToken = this.Tokenize();
                if (jsonToken == JsonToken.ArrayEnd)
                {
                    goto Block_8;
                }
                object obj = this.Read(type, typeIsHint);
                list.Add(obj);
                if (obj == null)
                {
                    if (!object.Equals(type, null) && TypeCoercionUtility.GetTypeInfo(type).IsValueType)
                    {
                        type = null;
                    }
                    flag = true;
                }
                else if (!object.Equals(type, null) && !TypeCoercionUtility.GetTypeInfo(type).IsAssignableFrom(TypeCoercionUtility.GetTypeInfo(obj.GetType())))
                {
                    if (TypeCoercionUtility.GetTypeInfo(obj.GetType()).IsAssignableFrom(TypeCoercionUtility.GetTypeInfo(type)))
                    {
                        type = obj.GetType();
                    }
                    else
                    {
                        type = null;
                        flag = true;
                    }
                }
                else if (!flag)
                {
                    type = obj.GetType();
                    flag = true;
                }
                jsonToken = this.Tokenize();
                if (jsonToken != JsonToken.ValueDelim)
                {
                    goto IL_1AB;
                }
            }
            throw new JsonDeserializationException("Unterminated JSON array.", this.index);
Block_8:
IL_1AB:
            if (jsonToken != JsonToken.ArrayEnd)
            {
                throw new JsonDeserializationException("Unterminated JSON array.", this.index);
            }
            this.index++;
            this.jsArrays.Push(list);
            if (object.Equals(type, null) || object.Equals(type, typeof(object)))
            {
                return(list.ToArray());
            }
            if (arrayType != null && arrayType.IsGenericType && object.Equals(arrayType.GetGenericTypeDefinition(), typeof(List <>)))
            {
                IList list2 = Activator.CreateInstance(arrayType, new object[]
                {
                    list.Count
                }) as IList;
                for (int i = 0; i < list.Count; i++)
                {
                    list2.Add(list[i]);
                }
                return(list2);
            }
            Array array = Array.CreateInstance(type, new int[]
            {
                list.Count
            });

            for (int j = 0; j < list.Count; j++)
            {
                array.SetValue(list[j], new int[]
                {
                    j
                });
            }
            return(array);
        }
Ejemplo n.º 8
0
 public Dictionary <string, MemberInfo> GetMemberMap(Type objectType)
 {
     if (TypeCoercionUtility.GetTypeInfo(typeof(IDictionary)).IsAssignableFrom(TypeCoercionUtility.GetTypeInfo(objectType)))
     {
         return(null);
     }
     return(this.CreateMemberMap(objectType));
 }
Ejemplo n.º 9
0
 private static bool IsNullable(Type type)
 {
     return(TypeCoercionUtility.GetTypeInfo(type).IsGenericType&& typeof(Nullable <>).Equals(type.GetGenericTypeDefinition()));
 }
Ejemplo n.º 10
0
        private object CoerceList(Type targetType, Type arrayType, IEnumerable value)
        {
            if (targetType.IsArray)
            {
                return(this.CoerceArray(targetType.GetElementType(), value));
            }
            ConstructorInfo[] constructors    = targetType.GetConstructors();
            ConstructorInfo   constructorInfo = null;

            foreach (ConstructorInfo constructorInfo2 in constructors)
            {
                ParameterInfo[] parameters = constructorInfo2.GetParameters();
                if (parameters.Length == 0)
                {
                    constructorInfo = constructorInfo2;
                }
                else if (parameters.Length == 1 && TypeCoercionUtility.GetTypeInfo(parameters[0].ParameterType).IsAssignableFrom(TypeCoercionUtility.GetTypeInfo(arrayType)))
                {
                    try
                    {
                        return(constructorInfo2.Invoke(new object[]
                        {
                            value
                        }));
                    }
                    catch
                    {
                    }
                }
            }
            if (object.Equals(constructorInfo, null))
            {
                throw new JsonTypeCoercionException(string.Format("Only objects with default constructors can be deserialized. ({0})", new object[]
                {
                    targetType.FullName
                }));
            }
            object obj;

            try
            {
                obj = constructorInfo.Invoke(null);
            }
            catch (TargetInvocationException ex)
            {
                if (ex.InnerException != null)
                {
                    throw new JsonTypeCoercionException(ex.InnerException.Message, ex.InnerException);
                }
                throw new JsonTypeCoercionException("Error instantiating " + targetType.FullName, ex);
            }
            MethodInfo method = TypeCoercionUtility.GetTypeInfo(targetType).GetMethod("AddRange");

            ParameterInfo[] array2 = (!object.Equals(method, null)) ? method.GetParameters() : null;
            Type            type   = (array2 != null && array2.Length == 1) ? array2[0].ParameterType : null;

            if (!object.Equals(type, null) && TypeCoercionUtility.GetTypeInfo(type).IsAssignableFrom(TypeCoercionUtility.GetTypeInfo(arrayType)))
            {
                try
                {
                    method.Invoke(obj, new object[]
                    {
                        value
                    });
                }
                catch (TargetInvocationException ex2)
                {
                    if (ex2.InnerException != null)
                    {
                        throw new JsonTypeCoercionException(ex2.InnerException.Message, ex2.InnerException);
                    }
                    throw new JsonTypeCoercionException("Error calling AddRange on " + targetType.FullName, ex2);
                }
                return(obj);
            }
            method = TypeCoercionUtility.GetTypeInfo(targetType).GetMethod("Add");
            array2 = ((!object.Equals(method, null)) ? method.GetParameters() : null);
            type   = ((array2 != null && array2.Length == 1) ? array2[0].ParameterType : null);
            if (!object.Equals(type, null))
            {
                IEnumerator enumerator = value.GetEnumerator();
                try
                {
                    while (enumerator.MoveNext())
                    {
                        object value2 = enumerator.Current;
                        try
                        {
                            method.Invoke(obj, new object[]
                            {
                                this.CoerceType(type, value2)
                            });
                        }
                        catch (TargetInvocationException ex3)
                        {
                            if (ex3.InnerException != null)
                            {
                                throw new JsonTypeCoercionException(ex3.InnerException.Message, ex3.InnerException);
                            }
                            throw new JsonTypeCoercionException("Error calling Add on " + targetType.FullName, ex3);
                        }
                    }
                }
                finally
                {
                    IDisposable disposable;
                    if ((disposable = (enumerator as IDisposable)) != null)
                    {
                        disposable.Dispose();
                    }
                }
                return(obj);
            }
            object result;

            try
            {
                result = Convert.ChangeType(value, targetType);
            }
            catch (Exception innerException)
            {
                throw new JsonTypeCoercionException(string.Format("Error converting {0} to {1}", new object[]
                {
                    value.GetType().FullName,
                    targetType.FullName
                }), innerException);
            }
            return(result);
        }
Ejemplo n.º 11
0
        internal object CoerceType(Type targetType, object value)
        {
            bool flag = TypeCoercionUtility.IsNullable(targetType);

            if (value == null)
            {
                if (!this.allowNullValueTypes && TypeCoercionUtility.GetTypeInfo(targetType).IsValueType&& !flag)
                {
                    throw new JsonTypeCoercionException(string.Format("{0} does not accept null as a value", new object[]
                    {
                        targetType.FullName
                    }));
                }
                return(value);
            }
            else
            {
                if (flag)
                {
                    Type[] genericArguments = targetType.GetGenericArguments();
                    if (genericArguments.Length == 1)
                    {
                        targetType = genericArguments[0];
                    }
                }
                Type type = value.GetType();
                if (TypeCoercionUtility.GetTypeInfo(targetType).IsAssignableFrom(TypeCoercionUtility.GetTypeInfo(type)))
                {
                    return(value);
                }
                if (TypeCoercionUtility.GetTypeInfo(targetType).IsEnum)
                {
                    if (value is string)
                    {
                        if (!Enum.IsDefined(targetType, value))
                        {
                            foreach (FieldInfo fieldInfo in TypeCoercionUtility.GetTypeInfo(targetType).GetFields())
                            {
                                string jsonName = JsonNameAttribute.GetJsonName(fieldInfo);
                                if (((string)value).Equals(jsonName))
                                {
                                    value = fieldInfo.Name;
                                    break;
                                }
                            }
                        }
                        return(Enum.Parse(targetType, (string)value));
                    }
                    value = this.CoerceType(Enum.GetUnderlyingType(targetType), value);
                    return(Enum.ToObject(targetType, value));
                }
                else
                {
                    if (value is IDictionary)
                    {
                        Dictionary <string, MemberInfo> dictionary;
                        return(this.CoerceType(targetType, (IDictionary)value, out dictionary));
                    }
                    if (TypeCoercionUtility.GetTypeInfo(typeof(IEnumerable)).IsAssignableFrom(TypeCoercionUtility.GetTypeInfo(targetType)) && TypeCoercionUtility.GetTypeInfo(typeof(IEnumerable)).IsAssignableFrom(TypeCoercionUtility.GetTypeInfo(type)))
                    {
                        return(this.CoerceList(targetType, type, (IEnumerable)value));
                    }
                    if (value is string)
                    {
                        if (object.Equals(targetType, typeof(DateTime)))
                        {
                            DateTime dateTime;
                            if (DateTime.TryParse((string)value, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.AllowInnerWhite | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.RoundtripKind, out dateTime))
                            {
                                return(dateTime);
                            }
                        }
                        else
                        {
                            if (object.Equals(targetType, typeof(Guid)))
                            {
                                return(new Guid((string)value));
                            }
                            if (object.Equals(targetType, typeof(char)))
                            {
                                if (((string)value).Length == 1)
                                {
                                    return(((string)value)[0]);
                                }
                            }
                            else if (object.Equals(targetType, typeof(Uri)))
                            {
                                Uri result;
                                if (Uri.TryCreate((string)value, UriKind.RelativeOrAbsolute, out result))
                                {
                                    return(result);
                                }
                            }
                            else if (object.Equals(targetType, typeof(Version)))
                            {
                                return(new Version((string)value));
                            }
                        }
                    }
                    else if (object.Equals(targetType, typeof(TimeSpan)))
                    {
                        return(new TimeSpan((long)this.CoerceType(typeof(long), value)));
                    }
                    TypeConverter converter = TypeDescriptor.GetConverter(targetType);
                    if (converter.CanConvertFrom(type))
                    {
                        return(converter.ConvertFrom(value));
                    }
                    converter = TypeDescriptor.GetConverter(type);
                    if (converter.CanConvertTo(targetType))
                    {
                        return(converter.ConvertTo(value, targetType));
                    }
                    object result2;
                    try
                    {
                        result2 = Convert.ChangeType(value, targetType);
                    }
                    catch (Exception innerException)
                    {
                        throw new JsonTypeCoercionException(string.Format("Error converting {0} to {1}", new object[]
                        {
                            value.GetType().FullName,
                            targetType.FullName
                        }), innerException);
                    }
                    return(result2);
                }
            }
        }
Ejemplo n.º 12
0
        private void PopulateObject(object result, Type objectType, Dictionary <string, MemberInfo> memberMap, Type genericDictionaryType)
        {
            if (this.Source[this.index] != JsonReader.OperatorObjectStart)
            {
                throw new JsonDeserializationException(JsonReader.ErrorExpectedObject, this.index);
            }

            JsonToken token;

            do
            {
                Type       memberType;
                MemberInfo memberInfo;

                // consume opening brace or delim
                this.index++;
                if (this.index >= this.SourceLength)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorUnterminatedObject, this.index);
                }

                // get next token
                token = this.Tokenize(this.Settings.AllowUnquotedObjectKeys);
                if (token == JsonToken.ObjectEnd)
                {
                    break;
                }

                if (token != JsonToken.String && token != JsonToken.UnquotedName)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorExpectedPropertyName, this.index);
                }

                // parse object member value
                string memberName = (token == JsonToken.String) ?
                                    (String)this.ReadString(null) :
                                    this.ReadUnquotedKey();

                if (genericDictionaryType == null && memberMap != null)
                {
                    // determine the type of the property/field
                    memberType = TypeCoercionUtility.GetMemberInfo(memberMap, memberName, out memberInfo);
                }
                else
                {
                    memberType = genericDictionaryType;
                    memberInfo = null;
                }

                // get next token
                token = this.Tokenize();
                if (token != JsonToken.NameDelim)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorExpectedPropertyNameDelim, this.index);
                }

                // consume delim
                this.index++;
                if (this.index >= this.SourceLength)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorUnterminatedObject, this.index);
                }

                // parse object member value
                object value = this.Read(memberType, false);

                if (result is IDictionary)
                {
                    if (objectType == null && this.Settings.IsTypeHintName(memberName))
                    {
                        result = this.Settings.Coercion.ProcessTypeHint((IDictionary)result, value as string, out objectType, out memberMap);
                    }
                    else
                    {
                        ((IDictionary)result)[memberName] = value;
                    }
                }
                else if (objectType.GetInterface(JsonReader.TypeGenericIDictionary) != null)
                {
                    throw new JsonDeserializationException(
                              String.Format(JsonReader.ErrorGenericIDictionary, objectType),
                              this.index);
                }
                else
                {
                    this.Settings.Coercion.SetMemberValue(result, memberType, memberInfo, value);
                }

                // get next token
                token = this.Tokenize();
            } while (token == JsonToken.ValueDelim);

            if (token != JsonToken.ObjectEnd)
            {
                throw new JsonDeserializationException(JsonReader.ErrorUnterminatedObject, this.index);
            }

            // consume closing brace
            this.index++;

            //return result;
        }
Ejemplo n.º 13
0
        internal object CoerceType(Type targetType, object value)
        {
            bool isNullable = TypeCoercionUtility.IsNullable(targetType);

            if (value == null)
            {
                if (!allowNullValueTypes &&
                    TCU.GetTypeInfo(targetType).IsValueType&&
                    !isNullable)
                {
                    throw new JsonTypeCoercionException(String.Format(TypeCoercionUtility.ErrorNullValueType, new System.Object[] { targetType.FullName }));
                }
                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 (TCU.GetTypeInfo(targetType).IsAssignableFrom(TCU.GetTypeInfo(actualType)))
            {
                return(value);
            }

            if (TCU.GetTypeInfo(targetType).IsEnum)
            {
                if (value is String)
                {
                    if (!Enum.IsDefined(targetType, value))
                    {
                        // if isn't a defined value perhaps it is the JsonName
                        foreach (FieldInfo field in TCU.GetTypeInfo(targetType).GetFields())
                        {
                            string jsonName = JsonNameAttribute.GetJsonName(field);
                            if (((string)value).Equals(jsonName))
                            {
                                value = field.Name;
                                break;
                            }
                        }
                    }

                    return(Enum.Parse(targetType, (string)value));
                }
                else
                {
                    value = this.CoerceType(Enum.GetUnderlyingType(targetType), value);
                    return(Enum.ToObject(targetType, value));
                }
            }

            // Value is of the wrong type and it has been deserialized as an IDictionary.
            // Previously coercion was supported
            // but this generally just caused more problems than it solved, so type hints are recommended now.
            // More specifically this can cause annoying problems with tags when a tag is referencing some object
            // for which there is no type info for (e.g the field has been removed), that data would have been
            // deserialized as an IDictionary, but when the tag gets the information it will try to coerce it
            // which will often fail horribly
            if (value is IDictionary)
            {
                return(null);
                // Dictionary<string, MemberInfo> memberMap;
                // return this.CoerceType(targetType, (IDictionary)value, out memberMap);
            }

            if (TCU.GetTypeInfo(typeof(IEnumerable)).IsAssignableFrom(TCU.GetTypeInfo(targetType)) &&
                TCU.GetTypeInfo(typeof(IEnumerable)).IsAssignableFrom(TCU.GetTypeInfo(actualType)))
            {
                return(this.CoerceList(targetType, actualType, (IEnumerable)value));
            }

            if (value is String)
            {
                if (Type.Equals(targetType, typeof(DateTime)))
                {
                    DateTime date;
                    if (DateTime.TryParse(
                            (string)value,
                            DateTimeFormatInfo.InvariantInfo,
                            DateTimeStyles.RoundtripKind | DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault,
                            out date))
                    {
                        return(date);
                    }
                }
                else if (Type.Equals(targetType, typeof(Guid)))
                {
                    // try-catch is pointless since will throw upon generic conversion
                    return(new Guid((string)value));
                }
                else if (Type.Equals(targetType, typeof(Char)))
                {
                    if (((string)value).Length == 1)
                    {
                        return(((string)value)[0]);
                    }
                }
                else if (Equals(targetType, typeof(Uri)))
                {
                    Uri uri;
                    if (Uri.TryCreate((string)value, UriKind.RelativeOrAbsolute, out uri))
                    {
                        return(uri);
                    }
                }
                else if (Type.Equals(targetType, typeof(Version)))
                {
                    // try-catch is pointless since will throw upon generic conversion
                    return(new Version((string)value));
                }
            }
            else if (Type.Equals(targetType, typeof(TimeSpan)))
            {
                return(new TimeSpan((long)this.CoerceType(typeof(Int64), value)));
            }

#if !WINPHONE_8
            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));
            }
#endif

            try
            {
                // fall back to basics
                return(Convert.ChangeType(value, targetType));
            }
            catch (Exception ex)
            {
                throw new JsonTypeCoercionException(
                          String.Format("Error converting {0} to {1}", new System.Object[] { value.GetType().FullName, targetType.FullName }), ex);
            }
        }