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); }
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); }