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);
            }
示例#2
0
            private object ReadObject(Type objectType)
            {
                if (this.Source[this.index] != JsonReader.OperatorObjectStart)
                {
                    throw new JsonDeserializationException(JsonReader.ErrorExpectedObject, this.index);
                }

                Type genericDictionaryType = null;
                Dictionary <string, MemberInfo> memberMap = null;
                Object result;

                if (objectType != null)
                {
                    result = this.Settings.Coercion.InstantiateObject(objectType, out memberMap);

                    if (memberMap == null)
                    {
                        // this allows specific IDictionary<string, T> to deserialize T
                        Type genericDictionary = objectType.GetInterface(JsonReader.TypeGenericIDictionary);
                        if (genericDictionary != null)
                        {
                            Type[] genericArgs = genericDictionary.GetGenericArguments();
                            if (genericArgs.Length == 2)
                            {
                                if (genericArgs[0] != typeof(String))
                                {
                                    throw new JsonDeserializationException(
                                              String.Format(JsonReader.ErrorGenericIDictionaryKeys, objectType),
                                              this.index);
                                }

                                if (genericArgs[1] != typeof(Object))
                                {
                                    genericDictionaryType = genericArgs[1];
                                }
                            }
                        }
                    }
                }
                else
                {
                    result = new Dictionary <String, Object>();
                }

                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);
            }
    protected virtual object ReadObject(Type objectType)
    {
        if (Source[index] != '{')
        {
            throw new JsonDeserializationException("Expected JSON object.", index);
        }
        Type type = null;
        Dictionary <string, MemberInfo> memberMap = null;
        object obj;

        if (objectType != null)
        {
            obj = Settings.Coercion.InstantiateObject(objectType, out memberMap);
            if (memberMap == null)
            {
                Type @interface = objectType.GetInterface("System.Collections.Generic.IDictionary`2");
                if (@interface != null)
                {
                    Type[] genericArguments = @interface.GetGenericArguments();
                    if (genericArguments.Length == 2)
                    {
                        if (genericArguments[0] != typeof(string))
                        {
                            throw new JsonDeserializationException($"Types which implement Generic IDictionary<TKey, TValue> need to have string keys to be deserialized. ({objectType})", index);
                        }
                        if (genericArguments[1] != typeof(object))
                        {
                            type = genericArguments[1];
                        }
                    }
                }
            }
        }
        else
        {
            obj = new Dictionary <string, object>();
        }
        JsonToken jsonToken;

        do
        {
            index++;
            if (index >= SourceLength)
            {
                throw new JsonDeserializationException("Unterminated JSON object.", index);
            }
            jsonToken = Tokenize(Settings.AllowUnquotedObjectKeys);
            switch (jsonToken)
            {
            default:
                throw new JsonDeserializationException("Expected JSON object property name.", index);

            case JsonToken.String:
            case JsonToken.UnquotedName:
            {
                string     text = (jsonToken != JsonToken.String) ? ReadUnquotedKey() : ((string)ReadString(null));
                Type       type2;
                MemberInfo memberInfo;
                if (type == null && memberMap != null)
                {
                    type2 = TypeCoercionUtility.GetMemberInfo(memberMap, text, out memberInfo);
                }
                else
                {
                    type2      = type;
                    memberInfo = null;
                }
                jsonToken = Tokenize();
                if (jsonToken != JsonToken.NameDelim)
                {
                    throw new JsonDeserializationException("Expected JSON object property name delimiter.", index);
                }
                index++;
                if (index >= SourceLength)
                {
                    throw new JsonDeserializationException("Unterminated JSON object.", index);
                }
                object obj2 = Read(type2, typeIsHint: false);
                if (obj is IDictionary)
                {
                    if (objectType == null && Settings.IsTypeHintName(text))
                    {
                        obj = Settings.Coercion.ProcessTypeHint((IDictionary)obj, obj2 as string, out objectType, out memberMap);
                    }
                    else
                    {
                        ((IDictionary)obj)[text] = obj2;
                    }
                }
                else
                {
                    if (objectType.GetInterface("System.Collections.Generic.IDictionary`2") != null)
                    {
                        throw new JsonDeserializationException($"Types which implement Generic IDictionary<TKey, TValue> also need to implement IDictionary to be deserialized. ({objectType})", index);
                    }
                    Settings.Coercion.SetMemberValue(obj, type2, memberInfo, obj2);
                }
                goto IL_0270;
            }

            case JsonToken.ObjectEnd:
                break;
            }
            break;
IL_0270:
            jsonToken = Tokenize();
        }while (jsonToken == JsonToken.ValueDelim);
        if (jsonToken != JsonToken.ObjectEnd)
        {
            throw new JsonDeserializationException("Unterminated JSON object.", index);
        }
        index++;
        return(obj);
    }