コード例 #1
0
		/** Creates a member map for the type */
		private Dictionary<string, MemberInfo> CreateMemberMap(Type objectType)
		{

			Dictionary<string, MemberInfo> memberMap;

			if (this.MemberMapCache.TryGetValue(objectType, out memberMap))
			{
				// map was stored in cache
				return memberMap;
			}

			// create a new map
			memberMap = new Dictionary<string, MemberInfo>();

			// load properties into property map
			PropertyInfo[] properties = objectType.GetProperties( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance );
			foreach (PropertyInfo info in properties)
			{
				if (!info.CanRead || !info.CanWrite)
				{
					continue;
				}

				if (JsonIgnoreAttribute.IsJsonIgnore(info))
				{
					continue;
				}

				string jsonName = JsonNameAttribute.GetJsonName(info);
				if (String.IsNullOrEmpty(jsonName))
				{
					memberMap[info.Name] = info;
				}
				else
				{
					memberMap[jsonName] = info;
				}
			}

			// load public fields into property map
			FieldInfo[] fields = objectType.GetFields( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance );
			foreach (FieldInfo info in fields)
			{
				if (!info.IsPublic && info.GetCustomAttributes(typeof(JsonMemberAttribute),true).Length == 0)
				{
					continue;
				}

				if (JsonIgnoreAttribute.IsJsonIgnore(info))
				{
					continue;
				}

				string jsonName = JsonNameAttribute.GetJsonName(info);
				if (String.IsNullOrEmpty(jsonName))
				{
					memberMap[info.Name] = info;
				}
				else
				{
					memberMap[jsonName] = info;
				}
			}

			// store in cache for repeated usage
			this.MemberMapCache[objectType] = memberMap;

			return memberMap;
		}
コード例 #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);
			}
		}
コード例 #3
0
		protected virtual void WriteObject(object value, Type type, bool serializePrivate)
		{
			bool appendDelim = false;

			if (settings.HandleCyclicReferences && !type.IsValueType)
			{
				int prevIndex = 0;
				if (this.previouslySerializedObjects.TryGetValue (value, out prevIndex)) {
					this.Writer.Write(JsonReader.OperatorObjectStart);
					this.WriteObjectProperty("@ref", prevIndex);
					this.WriteLine();
					this.Writer.Write(JsonReader.OperatorObjectEnd);
					return;
				} else {
					this.previouslySerializedObjects.Add (value, this.previouslySerializedObjects.Count);
				}
			}

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

				bool anonymousType = type.IsGenericType && (type.Name.StartsWith(JsonWriter.AnonymousTypePrefix) || type.Name.StartsWith(JsonWriter.AnonymousTypePrefix2));

				// serialize public properties
				PropertyInfo[] properties = type.GetProperties();
				foreach (PropertyInfo property in properties)
				{
					if (!property.CanRead) {
						if (Settings.DebugMode)
							Console.WriteLine ("Cannot serialize "+property.Name+" : cannot read");
						continue;
					}
					
					if (!property.CanWrite && !anonymousType) {
						if (Settings.DebugMode)
							Console.WriteLine ("Cannot serialize "+property.Name+" : cannot write");
						continue;
					}
					
					if (this.IsIgnored(type, property, value)) {
						if (Settings.DebugMode)
							Console.WriteLine ("Cannot serialize "+property.Name+" : is ignored by settings");
						continue;
					}
					
					if (property.GetIndexParameters ().Length != 0) {
						if (Settings.DebugMode)
							Console.WriteLine ("Cannot serialize "+property.Name+" : is indexed");
						continue;
					}
					
					object propertyValue = property.GetValue(value, null);
					if (this.IsDefaultValue(property, propertyValue)) {
						if (Settings.DebugMode)
							Console.WriteLine ("Cannot serialize "+property.Name+" : is default value");
						continue;
					}
				
					if (appendDelim)
						this.WriteObjectPropertyDelim();
					else
						appendDelim = true;

					// use Attributes here to control naming
					string propertyName = JsonNameAttribute.GetJsonName(property);
					if (String.IsNullOrEmpty(propertyName))
						propertyName = property.Name;

					this.WriteObjectProperty(propertyName, propertyValue);
				}

				// serialize public fields
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo field in fields)
				{
					if (field.IsStatic || (!field.IsPublic && field.GetCustomAttributes(typeof(JsonMemberAttribute),true).Length == 0)) {
						if (Settings.DebugMode)
							Console.WriteLine ("Cannot serialize "+field.Name+" : not public or is static (and does not have a JsonMember attribute)");
						continue;
					}
					
					if (this.IsIgnored(type, field, value)) {
						if (Settings.DebugMode)
							Console.WriteLine ("Cannot serialize "+field.Name+" : ignored by settings");
						continue;
					}

					object fieldValue = field.GetValue(value);
					if (this.IsDefaultValue(field, fieldValue)) {
						if (Settings.DebugMode)
							Console.WriteLine ("Cannot serialize "+field.Name+" : is default value");
						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 = field.Name;

					this.WriteObjectProperty(fieldName, fieldValue);
				}
			}
			finally
			{
				this.depth--;
			}

			if (appendDelim)
				this.WriteLine();
			
			this.Writer.Write(JsonReader.OperatorObjectEnd);
		}