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); }
internal object CoerceType(Type targetType, IDictionary newValues, object existingObject, out Dictionary <string, MemberInfo> memberMap) { // don't incurr the cost of member map for dictionaries if (typeof(IDictionary).IsAssignableFrom(targetType) && existingObject is IDictionary) { memberMap = null; } else { memberMap = this.CreateMemberMap(targetType); } if (memberMap != null) { // copy any values into new object foreach (object key in newValues.Keys) { MemberInfo memberInfo; Type memberType = TypeCoercionUtility.GetMemberInfo(memberMap, key as String, out memberInfo); this.SetMemberValue(existingObject, memberType, memberInfo, newValues[key]); } } else { // set the values IDictionary newValueDictionary = existingObject as IDictionary; if (newValueDictionary == null) { return(existingObject); } foreach (object key in newValues.Keys) { newValueDictionary[key as string] = newValues[key]; } } return(existingObject); }
private object CoerceList(Type targetType, Type arrayType, IEnumerable value) { if (targetType.IsArray) { return(this.CoerceArray(targetType.GetElementType(), value)); } // targetType serializes as a JSON array but is not an array // assume is an ICollection / IEnumerable with AddRange, Add, // or custom Constructor with which we can populate it // many ICollection types take an IEnumerable or ICollection // as a constructor argument. look through constructors for // a compatible match. ConstructorInfo[] ctors = targetType.GetConstructors(); ConstructorInfo defaultCtor = null; foreach (ConstructorInfo ctor in ctors) { ParameterInfo[] paramList = ctor.GetParameters(); if (paramList.Length == 0) { // save for in case cannot find closer match defaultCtor = ctor; continue; } if (paramList.Length == 1 && paramList[0].ParameterType.IsAssignableFrom(arrayType)) { try { // invoke first constructor that can take this value as an argument return(ctor.Invoke( new object[] { value } )); } catch { // there might exist a better match continue; } } } if (defaultCtor == null) { throw new JsonTypeCoercionException( String.Format(TypeCoercionUtility.ErrorDefaultCtor, targetType.FullName)); } object collection; try { // always try-catch Invoke() to expose real exception collection = defaultCtor.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); } // many ICollection types have an AddRange method // which adds all items at once MethodInfo method = targetType.GetMethod("AddRange"); ParameterInfo[] parameters = (method == null) ? null : method.GetParameters(); Type paramType = (parameters == null || parameters.Length != 1) ? null : parameters[0].ParameterType; if (paramType != null && paramType.IsAssignableFrom(arrayType)) { try { // always try-catch Invoke() to expose real exception // add all members in one method method.Invoke( collection, new object[] { value }); } catch (TargetInvocationException ex) { if (ex.InnerException != null) { throw new JsonTypeCoercionException(ex.InnerException.Message, ex.InnerException); } throw new JsonTypeCoercionException("Error calling AddRange on " + targetType.FullName, ex); } return(collection); } else { // many ICollection types have an Add method // which adds items one at a time method = targetType.GetMethod("Add"); parameters = (method == null) ? null : method.GetParameters(); paramType = (parameters == null || parameters.Length != 1) ? null : parameters[0].ParameterType; if (paramType != null) { var enumerator = TypeCoercionUtility.GetEnumerator(value); if (enumerator == null) { throw new JsonTypeCoercionException(string.Format("Requested to get an IEnumerator of a value that doesn't implement the IEnumerable interface.\nValue: {0}\nValue's type: {1}", value, value.GetType().FullName)); } while (enumerator.MoveNext()) { // loop through adding items to collection object item = enumerator.Current; try { // always try-catch Invoke() to expose real exception method.Invoke( collection, new object[] { this.CoerceType(paramType, item) }); } catch (TargetInvocationException ex) { if (ex.InnerException != null) { throw new JsonTypeCoercionException(ex.InnerException.Message, ex.InnerException); } throw new JsonTypeCoercionException("Error calling Add on " + targetType.FullName, ex); } } IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } return(collection); } } 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); } }
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 this is a crazy server date string, clean up the server junk. if (((string)value).StartsWith("/Date(") && ((string)value).EndsWith(")/")) { date = new DateTime(1970, 1, 1, 0, 0, 0, 0); value = ((string)value).Replace("/Date(", "").Replace(")/", "").Replace("+0000", ""); date = date.AddMilliseconds(long.Parse((string)value)); return(date); } // Try a regular DateTime parse 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))); } 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)); } 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); } }
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); }
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; } } } //Julien: Added check for enums (previously didn't have try catch and wasn't case-insensitive) //we don't want JSONFx to entirely abandon the parsing just because the user badly entered an enum //instead just return null object output; try { output = Enum.Parse(targetType, (string)value, true); } catch (ArgumentException) { //If value is 'null', handle that gracefully. Can happen when enum is stored as string on other end, e.g. w/ DBs if (((string)value).ToLower() != "null") { UnityEngine.Debug.LogWarning("JSONFx could not parse '" + (string)value + "' as a(n) " + targetType.ToString()); } //output = Activator.CreateInstance(targetType); //if we want to return the default for this enum output = null; } return(output); } 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))); } //Julien: Added to be able to deserialize times in epoch format //Commented because of inconsistencies: Java uses milliseconds & .NET uses ticks //else if (targetType == typeof(DateTime) && value is Decimal) //{ // return new DateTime((long)this.CoerceType(typeof(Int64), value)); //} 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)); } try { // fall back to basics return(Convert.ChangeType(value, targetType)); } catch (Exception ex) { throw new JsonTypeCoercionException( String.Format("Error converting {0} to {1} for value: " + value.ToString(), value.GetType().FullName, targetType.FullName), ex); } }
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) { // AKS: Try to parse enum's for upper-case too, since we always serialize as lower-case if (Enum.IsDefined(targetType, value)) { return(Enum.Parse(targetType, (string)value)); } if (Enum.IsDefined(targetType, ((string)value).ToUpper())) { return(Enum.Parse(targetType, ((string)value).ToUpper())); } // 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 (targetType.IsPrimitive == false && targetType != typeof(string)) // { // ConstructorInfo jsonConstructor = targetType.GetConstructors().FirstOrDefault(x => Attribute.IsDefined(x, typeof(JsonConstructor), true)); // if (jsonConstructor != null && jsonConstructor.GetParameters().Count() == 1) // { // Console.Write("JsonConstructor! " + targetType.Name); // Type constructorArgType = jsonConstructor.GetParameters()[0].ParameterType; // return jsonConstructor.Invoke(new object[] { CoerceType(constructorArgType, value) }); // } // // MethodInfo jsonFactory = targetType.GetMethods().FirstOrDefault(x => Attribute.IsDefined(x, typeof(JsonFactoryMethod), true)); // if (jsonFactory != null && jsonFactory.GetParameters().Count() == 1) // { // Console.Write("JsonFactory! " + targetType.Name); // Type factoryArgType = jsonFactory.GetParameters()[0].ParameterType; // return jsonFactory.Invoke(null, new object[] { CoerceType(factoryArgType, 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))); } 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)); } 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); } }
protected virtual void WriteObject(object value, Type type) { bool appendDelim = false; this.Writer.Write(JsonReader.OperatorObjectStart); this.depth++; if (this.depth > this.settings.MaxDepth) { throw new JsonSerializationException(String.Format(JsonWriter.ErrorMaxDepth, this.settings.MaxDepth)); } try { if (!String.IsNullOrEmpty(this.settings.TypeHintName)) { if (appendDelim) { this.WriteObjectPropertyDelim(); } else { appendDelim = true; } this.WriteObjectProperty(this.settings.TypeHintName, type.FullName + ", " + type.Assembly.GetName().Name); } #if JSONFX_SERIALIZE_PROPERTIES bool anonymousType = type.IsGenericType && type.Name.StartsWith(JsonWriter.AnonymousTypePrefix); // serialize public properties IList <PropertyInfo> properties = TypeCoercionUtility.GetAllProperties(type); // PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo property in properties) { if (!property.CanRead) { continue; } if (!property.CanWrite && !anonymousType) { continue; } if (this.IsIgnored(type, property, value)) { continue; } if (property.PropertyType == typeof(Action)) { continue; } object propertyValue = property.GetValue(value, null); if (this.IsDefaultValue(property, propertyValue)) { continue; } if (appendDelim) { this.WriteObjectPropertyDelim(); } else { appendDelim = true; } // use Attributes here to control naming string propertyName = JsonNameAttribute.GetJsonName(property); if (String.IsNullOrEmpty(propertyName)) { propertyName = NameResolver.CSharpToJson(property.Name); // propertyName = property.Name; } this.WriteObjectProperty(propertyName, propertyValue); } #endif // serialize public fields IList <FieldInfo> fields = TypeCoercionUtility.GetAllFields(type); // FieldInfo[] fields = type.GetFields(); foreach (FieldInfo field in fields) { // if (!field.IsPublic || field.IsStatic) // { // continue; // } if (field.IsPrivate) { int breakhere = 1; ++breakhere; } if (/*field.IsPrivate ||*/ field.IsStatic) { continue; } if (this.IsIgnored(type, field, value)) { continue; } if (field.FieldType == typeof(Action)) { continue; } object fieldValue = field.GetValue(value); if (this.IsDefaultValue(field, fieldValue)) { continue; } if (appendDelim) { this.WriteObjectPropertyDelim(); this.WriteLine(); } else { appendDelim = true; } // use Attributes here to control naming string fieldName = JsonNameAttribute.GetJsonName(field); if (String.IsNullOrEmpty(fieldName)) { fieldName = NameResolver.CSharpToJson(field.Name); // fieldName = field.Name; } this.WriteObjectProperty(fieldName, fieldValue); } } finally { this.depth--; } if (appendDelim) { this.WriteLine(); } this.Writer.Write(JsonReader.OperatorObjectEnd); }
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); }
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); } /* * if (memberInfo == null && memberType == null) * { * Debug.LogErrorFormat("Can't find MemberInfo with Name - {0}, Type - {1}. You need to create it in object: {2}", * memberName, value.GetType().Name, result.GetType().Name); * } */ // 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 (this.Source[this.index] != '{') { throw new JsonDeserializationException("Expected JSON object.", this.index); } Type type = null; Dictionary <string, MemberInfo> dictionary = null; object obj; if (objectType != null) { obj = this.Settings.Coercion.InstantiateObject(objectType, out dictionary); if (dictionary == 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(string.Format("Types which implement Generic IDictionary<TKey, TValue> need to have string keys to be deserialized. ({0})", objectType), this.index); } if (genericArguments[1] != typeof(object)) { type = genericArguments[1]; } } } } } else { obj = new Dictionary <string, object>(); } JsonToken jsonToken; for (;;) { this.index++; if (this.index >= this.SourceLength) { break; } jsonToken = this.Tokenize(this.Settings.AllowUnquotedObjectKeys); if (jsonToken == JsonToken.ObjectEnd) { goto Block_9; } if (jsonToken != JsonToken.String && jsonToken != JsonToken.UnquotedName) { goto Block_11; } string text = (jsonToken != JsonToken.String) ? this.ReadUnquotedKey() : ((string)this.ReadString(null)); MemberInfo memberInfo; Type type2; if (type == null && dictionary != null) { type2 = TypeCoercionUtility.GetMemberInfo(dictionary, text, out memberInfo); } else { type2 = type; memberInfo = null; } jsonToken = this.Tokenize(); if (jsonToken != JsonToken.NameDelim) { goto Block_15; } this.index++; if (this.index >= this.SourceLength) { goto Block_16; } object obj2 = this.Read(type2, false); if (obj is IDictionary) { if (objectType == null && this.Settings.IsTypeHintName(text)) { obj = this.Settings.Coercion.ProcessTypeHint((IDictionary)obj, obj2 as string, out objectType, out dictionary); } else { ((IDictionary)obj)[text] = obj2; } } else { if (objectType.GetInterface("System.Collections.Generic.IDictionary`2") != null) { goto Block_20; } this.Settings.Coercion.SetMemberValue(obj, type2, memberInfo, obj2); } jsonToken = this.Tokenize(); if (jsonToken != JsonToken.ValueDelim) { goto IL_281; } } throw new JsonDeserializationException("Unterminated JSON object.", this.index); Block_9: goto IL_281; Block_11: throw new JsonDeserializationException("Expected JSON object property name.", this.index); Block_15: throw new JsonDeserializationException("Expected JSON object property name delimiter.", this.index); Block_16: throw new JsonDeserializationException("Unterminated JSON object.", this.index); Block_20: throw new JsonDeserializationException(string.Format("Types which implement Generic IDictionary<TKey, TValue> also need to implement IDictionary to be deserialized. ({0})", objectType), this.index); IL_281: if (jsonToken != JsonToken.ObjectEnd) { throw new JsonDeserializationException("Unterminated JSON object.", this.index); } this.index++; return(obj); }
private object ReadObject(Type objectType) { object obj2; JsonToken token; if (this.Source[this.index] != '{') { throw new JsonDeserializationException("Expected JSON object.", this.index); } Type type = null; Dictionary <string, MemberInfo> memberMap = null; if (objectType != null) { #region 这里是映射JsonWriter(619行)所设定的特殊类型 if (objectType == typeof(Vector2)) { obj2 = new Vector2(); memberMap = this.Settings.Coercion.CreateFieldMemberMap(objectType); } else if (objectType == typeof(Vector3)) { obj2 = new Vector3(); memberMap = this.Settings.Coercion.CreateFieldMemberMap(objectType); } else if (objectType == typeof(Vector4)) { obj2 = new Vector4(); memberMap = this.Settings.Coercion.CreateFieldMemberMap(objectType); } #endregion else { obj2 = this.Settings.Coercion.InstantiateObject(objectType, out memberMap); } if (memberMap == null) { Type type2 = objectType.GetInterface("System.Collections.Generic.IDictionary`2"); if (type2 != null) { Type[] genericArguments = type2.GetGenericArguments(); if (genericArguments.Length == 2) { if (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})", objectType), this.index); } if (genericArguments[1] != typeof(object)) { type = genericArguments[1]; } } } } } else { obj2 = new Dictionary <string, object>(); } do { Type type3; MemberInfo info; this.index++; if (this.index >= this.SourceLength) { throw new JsonDeserializationException("Unterminated JSON object.", this.index); } token = this.Tokenize(this.Settings.AllowUnquotedObjectKeys); if (token == JsonToken.ObjectEnd) { break; } if ((token != JsonToken.String) && (token != JsonToken.UnquotedName)) { throw new JsonDeserializationException("Expected JSON object property name.", this.index); } string memberName = (token != JsonToken.String) ? this.ReadUnquotedKey() : ((string)this.ReadString(null)); if ((type == null) && (memberMap != null)) { type3 = TypeCoercionUtility.GetMemberInfo(memberMap, memberName, out info); } else { type3 = type; info = null; } if (this.Tokenize() != JsonToken.NameDelim) { throw new JsonDeserializationException("Expected JSON object property name delimiter.", this.index); } this.index++; if (this.index >= this.SourceLength) { throw new JsonDeserializationException("Unterminated JSON object.", this.index); } object obj3 = this.Read(type3, false); if (obj2 is IDictionary) { if ((objectType == null) && this.Settings.IsTypeHintName(memberName)) { obj2 = this.Settings.Coercion.ProcessTypeHint((IDictionary)obj2, obj3 as string, out objectType, out memberMap); } else { ((IDictionary)obj2)[memberName] = obj3; } } else { if (objectType.GetInterface("System.Collections.Generic.IDictionary`2") != 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); } this.Settings.Coercion.SetMemberValue(obj2, type3, info, obj3); } token = this.Tokenize(); }while (token == JsonToken.ValueDelim); if (token != JsonToken.ObjectEnd) { throw new JsonDeserializationException("Unterminated JSON object.", this.index); } this.index++; return(obj2); }
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)); } } if (value is IDictionary) { 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); } }
private object ReadObject(Type objectType) { if (this.Source[this.index] != JsonReader.OperatorObjectStart) { throw new JsonDeserializationException(JsonReader.ErrorExpectedObject, this.index); } // If this is a Date, then we should be reading an EJSON Date if (objectType != null && objectType == typeof(DateTime)) { // Read an EJSON result instead var ejsonDateResult = this.ReadObject(typeof(Meteor.EJSON.EJSONDate)) as Meteor.EJSON.EJSONDate; var returnDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(ejsonDateResult.date * 10000L); return(returnDate); } // If this is a byte[] destination and we're reading an object, we're handling an EJSON UInt8 array if (objectType != null && objectType == typeof(byte[])) { var ejsonBinaryResult = this.ReadObject(typeof(Meteor.EJSON.EJSONUInt8Array)) as Meteor.EJSON.EJSONUInt8Array; var returnBytes = System.Convert.FromBase64String(ejsonBinaryResult.binary); return(returnBytes); } 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); } 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); }
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; }
public virtual object CoerceType(Type targetType, object value) { bool flag = TypeCoercionUtility.IsNullable(targetType); if (value == null) { if (!this.allowNullValueTypes && targetType.IsValueType && !flag) { throw new JsonTypeCoercionException(string.Format("{0} does not accept null as a value", targetType.FullName)); } return(value); } else { if (flag) { Type[] genericArguments = targetType.GetGenericArguments(); if (genericArguments.Length == 1) { targetType = genericArguments[0]; } } Type type = value.GetType(); if (targetType.IsAssignableFrom(type)) { return(value); } if (targetType.IsEnum) { if (value is string) { if (!Enum.IsDefined(targetType, value)) { foreach (FieldInfo fieldInfo in 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 (typeof(IEnumerable).IsAssignableFrom(targetType) && typeof(IEnumerable).IsAssignableFrom(type)) { return(this.CoerceList(targetType, type, (IEnumerable)value)); } if (value is string) { if (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 (targetType == typeof(Guid)) { return(new Guid((string)value)); } if (targetType == typeof(char)) { if (((string)value).Length == 1) { return(((string)value)[0]); } } else if (targetType == typeof(Uri)) { Uri result; if (Uri.TryCreate((string)value, UriKind.RelativeOrAbsolute, out result)) { return(result); } } else if (targetType == typeof(Version)) { return(new Version((string)value)); } } } else if (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}", value.GetType().FullName, targetType.FullName), innerException); } return(result2); } } }