예제 #1
0
        public virtual void Write(Enum value)
        {
            string enumName = null;

            Type type = value.GetType();

            if (type.IsDefined(typeof(FlagsAttribute), true) && !Enum.IsDefined(type, value))
            {
                Enum[]   flags     = JsonWriter.GetFlagList(type, value);
                string[] flagNames = new string[flags.Length];
                for (int i = 0; i < flags.Length; i++)
                {
                    flagNames[i] = JsonNameAttribute.GetJsonName(flags[i]);
                    if (String.IsNullOrEmpty(flagNames[i]))
                    {
                        flagNames[i] = flags[i].ToString("f");
                    }
                }
                enumName = String.Join(", ", flagNames);
            }
            else
            {
                enumName = JsonNameAttribute.GetJsonName(value);
                if (String.IsNullOrEmpty(enumName))
                {
                    enumName = value.ToString("f");
                }
            }

            this.Write(enumName);
        }
예제 #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
        /** 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();
            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();
            foreach (FieldInfo info in fields)
            {
                if (!info.IsPublic)
                {
                    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);
        }
        /** 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
            Type tp = objectType;

            while (tp != null)
            {
                PropertyInfo[] properties = TCU.GetTypeInfo(tp).GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                for (int i = 0; i < properties.Length; i++)
                {
                    PropertyInfo info = properties [i];
                    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 = TCU.GetTypeInfo(tp).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                foreach (FieldInfo info in fields)
                {
                    if (!info.IsPublic &&
        #if WINDOWS_STORE
                        info.GetCustomAttribute <JsonMemberAttribute>(false) == null
        #else
                        info.GetCustomAttributes(typeof(JsonMemberAttribute), false).Length == 0
        #endif
                        )
                    {
                        continue;
                    }

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

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

                tp = tp.BaseType;
            }

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

            return(memberMap);
        }
        public void GetMemberWritingMap(Type objectType, JsonWriterSettings settings, out KeyValuePair <string, FieldInfo>[] outFields, out KeyValuePair <string, PropertyInfo>[] outProps)
        {
            if (writingMaps == null)
            {
                writingMaps = new Dictionary <Type, KeyValuePair <KeyValuePair <string, FieldInfo>[], KeyValuePair <string, PropertyInfo>[]> > ();
            }

            KeyValuePair <KeyValuePair <string, FieldInfo>[], KeyValuePair <string, PropertyInfo>[]> pair;

            if (writingMaps.TryGetValue(objectType, out pair))
            {
                outFields = pair.Key;
                outProps  = pair.Value;
                return;
            }

            bool anonymousType = objectType.IsGenericType && objectType.Name.StartsWith(JsonWriter.AnonymousTypePrefix);

            Type tp = objectType;

            if (fieldList == null)
            {
                fieldList = new List <KeyValuePair <string, FieldInfo> > ();
            }

            if (propList == null)
            {
                propList = new List <KeyValuePair <string, PropertyInfo> > ();
            }

            fieldList.Clear();
            propList.Clear();

            while (tp != null)
            {
                FieldInfo[] fields = tp.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
                for (int j = 0; j < fields.Length; j++)
                {
                    FieldInfo field = fields[j];

                    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 (settings.IsIgnored(objectType, field, null))
                    {
                        //if (Settings.DebugMode)
                        //	Console.WriteLine ("Cannot serialize " + field.Name + " : ignored by settings");
                        continue;
                    }

                    // use Attributes here to control naming
                    string fieldName = JsonNameAttribute.GetJsonName(field);
                    if (String.IsNullOrEmpty(fieldName))
                    {
                        fieldName = field.Name;
                    }

                    fieldList.Add(new KeyValuePair <string, FieldInfo> (fieldName, field));
                }

                PropertyInfo[] properties = tp.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
                for (int j = 0; j < properties.Length; j++)
                {
                    PropertyInfo property = properties[j];

                    //Console.WriteLine (property.Name);
                    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 (settings.IsIgnored(objectType, property, null))
                    {
                        //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;
                    }


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

                    propList.Add(new KeyValuePair <string, PropertyInfo>(propertyName, property));
                }

                tp = tp.BaseType;
            }

            outFields = fieldList.ToArray();
            outProps  = propList.ToArray();

            pair = new KeyValuePair <KeyValuePair <string, FieldInfo>[], KeyValuePair <string, PropertyInfo>[]> (outFields, outProps);

            writingMaps[objectType] = pair;
        }
예제 #6
0
        protected virtual void WriteObject(object value, Type type)
        {
            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);

                // 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.GetGetMethod().Invoke(value, null);
                    //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();
                foreach (FieldInfo field in fields)
                {
                    if (!field.IsPublic || field.IsStatic)
                    {
                        if (Settings.DebugMode)
                        {
                            Console.WriteLine("Cannot serialize " + field.Name + " : not public or is static");
                        }
                        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);
        }