/// <summary>
        /// Goes through a deserialized JSON object (a Dictionary&lt;string, object&gt; or a newtonsoft JObject) and updates all field an properties of this instance.
        /// </summary>
        /// <param name="value">The value.</param>
        public void FromJsonIntermediateObject(object value)
        {
            if (value == null)
            {
                // TODO: what should the method do then?
                return;
            }

            Type type = this.GetType();

            MemberInfo[] fieldAndPropertyInfos = type.GetProperties().Select(prop => (MemberInfo)prop).Union(type.GetFields().Select(field => (MemberInfo)field)).ToArray();

            // we do this here so there's no need to repeatedly cast the object within each pass of each for loop
            JObject valueAsJObject = value as JObject;
            Dictionary <string, object> valueAsDictionary = value as Dictionary <string, object>;

            if (valueAsJObject == null && valueAsDictionary == null)
            {
                throw new FormatException("Unsupported intermediate format");
            }

            foreach (MemberInfo member in fieldAndPropertyInfos)
            {
                FieldInfo    field        = member as FieldInfo;
                PropertyInfo property     = member as PropertyInfo;
                object[]     allAtributes = member.GetCustomAttributes(true);

                // If we don't have any custom attributes for this member, ignore it
                if (allAtributes == null)
                {
                    continue;
                }

                JsonNameAttribute nameAttribute = allAtributes.FirstOrDefault(attribute => attribute is JsonNameAttribute) as JsonNameAttribute;

                // If we don't have a JsonName attribute for this member, ignore it
                if (nameAttribute == null)
                {
                    continue;
                }

                string jsonPropertyName = nameAttribute.Name;

                Type memberType = field == null ? property.PropertyType : field.FieldType;

                object memberValue = null;

                if (valueAsJObject != null && valueAsJObject[jsonPropertyName] != null)
                {
                    memberValue = valueAsJObject[jsonPropertyName];
                }
                else if (valueAsDictionary != null && valueAsDictionary.ContainsKey(jsonPropertyName))
                {
                    memberValue = valueAsDictionary[jsonPropertyName];
                }

                this.SetMemberValue(member, ConvertMember(memberValue, memberType));
            }
        }
        /// <summary>
        /// Converts this instance to a Dictionary&lt;string, object&gt; that is ready to be serialized to a Ruby-compatible JSON.
        /// </summary>
        /// <returns>A Dictionary&lt;string, object&gt;</returns>
        public Dictionary <string, object> ToJsonIntermediateObject()
        {
            Dictionary <string, object> result = new Dictionary <string, object>();
            Type type = this.GetType();

            MemberInfo[] fieldAndPropertyInfos = type.GetProperties().Select(prop => (MemberInfo)prop).Union(type.GetFields().Select(field => (MemberInfo)field)).ToArray();

            foreach (MemberInfo member in fieldAndPropertyInfos)
            {
                FieldInfo    field    = member as FieldInfo;
                PropertyInfo property = member as PropertyInfo;

                object[] allAtributes = member.GetCustomAttributes(true);
                if (allAtributes != null)
                {
                    JsonNameAttribute nameAttribute = allAtributes.FirstOrDefault(attribute => attribute is JsonNameAttribute) as JsonNameAttribute;

                    object memberValue = property == null?field.GetValue(this) : property.GetValue(this, null);

                    if (nameAttribute != null && memberValue != null)
                    {
                        string jsonPropertyName = nameAttribute.Name;

                        Type propertyType = property == null ? field.FieldType : property.PropertyType;

                        if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>))
                        {
                            propertyType = propertyType.GetGenericArguments()[0];
                        }

                        if (propertyType.IsSubclassOf(typeof(JsonConvertibleObject)))
                        {
                            result.Add(jsonPropertyName, ((JsonConvertibleObject)memberValue).ToJsonIntermediateObject());
                        }
                        else if (propertyType.IsEnum)
                        {
                            string value = memberValue.ToString();
                            JsonNameAttribute[] attributes = (JsonNameAttribute[])propertyType.GetMember(value)[0].GetCustomAttributes(typeof(JsonNameAttribute), false);

                            if (attributes.Length != 0)
                            {
                                result.Add(jsonPropertyName, attributes[0].Name);
                            }
                            else
                            {
                                result.Add(jsonPropertyName, memberValue.ToString());
                            }
                        }
                        else
                        {
                            if (memberValue != null)
                            {
                                result.Add(jsonPropertyName, memberValue);
                            }
                        }
                    }
                }
            }

            return(result);
        }