private static object ToObject(IJSonObject source, object destination, Type oType)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (destination == null)
            {
                throw new ArgumentNullException("destination");
            }

            if (!source.IsEnumerable || source.Names == null)
            {
                throw new ArgumentException("Source is not a JSON Object");
            }

            JSonSerializableAttribute jsonAttribute = ReflectionHelper.GetCustomAttribute <JSonSerializableAttribute>(oType);

            if (jsonAttribute == null)
            {
                throw new JSonException("Object doesn't marked with JSonSerializable attribute");
            }

            // get members that will be serialized:
#if WINDOWS_STORE
            IEnumerable <FieldInfo>    fieldMembers    = ReflectionHelper.GetFields(oType);
            IEnumerable <PropertyInfo> propertyMembers = ReflectionHelper.GetProperties(oType);
#else
            IEnumerable <FieldInfo>    fieldMembers    = ReflectionHelper.GetFields(oType, jsonAttribute.Flags);
            IEnumerable <PropertyInfo> propertyMembers = ReflectionHelper.GetProperties(oType, jsonAttribute.Flags);
#endif

            // deserialize all fields:
            foreach (FieldInfo fieldInfo in fieldMembers)
            {
                ToObjectSetField(source, destination, oType, jsonAttribute, fieldInfo);
            }

            // deserialize all properties:
            foreach (PropertyInfo propertyInfo in propertyMembers)
            {
                ToObjectSetProperty(source, destination, oType, jsonAttribute, propertyInfo);
            }

            return(destination);
        }
        private static void ToObjectSetProperty(IJSonObject source, object destination, Type oType, JSonSerializableAttribute jsonAttribute, PropertyInfo propertyInfo)
        {
            // there must be a getter defined:
            if (!propertyInfo.CanWrite)
            {
                return;
            }

            JSonIgnoreAttribute ignore = ReflectionHelper.GetCustomAttribute <JSonIgnoreAttribute>(propertyInfo);

            if (ignore != null)
            {
                return;
            }

            JSonMemberAttribute attr = ReflectionHelper.GetCustomAttribute <JSonMemberAttribute>(propertyInfo);

            if (attr == null && !jsonAttribute.AllowAllProperties)
            {
                return;
            }

            string name = attr != null && !string.IsNullOrEmpty(attr.Name) ? attr.Name : propertyInfo.Name;
            Type   type = attr != null && attr.ReadAs != null ? attr.ReadAs : propertyInfo.PropertyType;

            if (source.Contains(name))
            {
                propertyInfo.SetValue(destination, ToObject(source[name], type), null);
            }
            else
            if (attr != null)
            {
                if (attr.DefaultValue != null)
                {
                    propertyInfo.SetValue(destination, ToObject(attr.DefaultValue, type), null);
                }
                else
                if (!attr.SuppressThrowWhenMissing && !attr.SkipWhenNull)
                {
                    throw new JSonMemberMissingException("Missing required property", oType, name);
                }
            }
            else
            if (!jsonAttribute.SuppressThrowWhenMissing)
            {
                throw new JSonMemberMissingException("Property value not provided", oType, name);
            }
        }
        private static void ToObjectSetField(IJSonObject source, object destination, Type oType, JSonSerializableAttribute jsonAttribute, FieldInfo fieldInfo)
        {
            if (fieldInfo.IsLiteral)
            {
                return;
            }

            JSonIgnoreAttribute ignore = ReflectionHelper.GetCustomAttribute <JSonIgnoreAttribute>(fieldInfo);

            if (ignore != null)
            {
                return;
            }

            JSonMemberAttribute attr = ReflectionHelper.GetCustomAttribute <JSonMemberAttribute>(fieldInfo);

            if (attr == null && !jsonAttribute.AllowAllFields)
            {
                return;
            }

            string name = attr != null && !string.IsNullOrEmpty(attr.Name) ? attr.Name : fieldInfo.Name;
            Type   type = attr != null && attr.ReadAs != null ? attr.ReadAs : fieldInfo.FieldType;

            if (source.Contains(name))
            {
                fieldInfo.SetValue(destination, ToObject(source[name], type));
            }
            else
            if (attr != null)
            {
                if (attr.DefaultValue != null)
                {
                    fieldInfo.SetValue(destination, ToObject(attr.DefaultValue, type));
                }
                else
                if (!attr.SuppressThrowWhenMissing && !attr.SkipWhenNull)
                {
                    throw new JSonMemberMissingException("Missing required field", oType, name);
                }
            }
            else
            if (!jsonAttribute.SuppressThrowWhenMissing)
            {
                throw new JSonMemberMissingException("Field value not provided", oType, name);
            }
        }