Ejemplo n.º 1
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 WINPHONE_8
            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;
        }
Ejemplo n.º 2
0
        internal object CoerceType(Type targetType, object value)
        {
            bool isNullable = TypeCoercionUtility.IsNullable(targetType);

            if (value == null)
            {
                if (!allowNullValueTypes &&
                    targetType.IsValueType &&
                    !isNullable)
                {
                    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 (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 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 !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}", value.GetType().FullName, targetType.FullName), ex);
            }
        }