internal JsonMember(FieldInfo field, int defaultOrder)
        {
            getter = field.GetValue;
            setter = field.SetValue;

            var dataMember = field.GetCustomAttribute <DataMemberAttribute>();

            Name             = dataMember?.Name ?? field.Name;
            Order            = dataMember?.Order ?? defaultOrder;
            EmitDefaultValue = dataMember?.EmitDefaultValue ?? true;

            this.type = TypeDetails.Get(field.FieldType);

            CanRead = true;
        }
        internal JsonMember(PropertyInfo property, int defaultOrder)
        {
            getter = property.GetValue;
            setter = property.SetValue;

            var dataMember = property.GetCustomAttribute <DataMemberAttribute>();

            Name             = dataMember?.Name ?? property.Name;
            Order            = dataMember?.Order ?? defaultOrder;
            EmitDefaultValue = dataMember?.EmitDefaultValue ?? true;

            this.type = TypeDetails.Get(property.PropertyType);

            CanRead = property.CanRead;
        }
        private object DeserializeValue(Type type, JsonNode value)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (value.Type == JsonType.Null)
            {
                return(null);
            }

            var typeDetails = TypeDetails.Get(type);

            if (typeDetails.JsonConverter != null)
            {
                return(typeDetails.JsonConverter.FromJson(value));
            }
            else if (typeDetails.IsEnum)
            {
                return(Enum.Parse(type, value.ToString(), ignoreCase: true));
            }
            else if (type.IsArray)
            {
                return(DeserializeArray(type, (JsonArray)value));
            }
            else if (typeDetails.IsList)
            {
                return(DeserializeList(type, (JsonArray)value));
            }
            else
            {
                var contract = JsonModelCache.Get(type);

                return(DeserializeObject(contract, (JsonObject)value));
            }
        }
        private JsonNode ReadValue(TypeDetails type, object value)
        {
            if (value == null)
            {
                return(XNull.Instance);
            }

            if (type.JsonConverter != null)
            {
                return(type.JsonConverter.ToJson(value));
            }
            else if (type.IsArray)
            {
                switch (Type.GetTypeCode(type.ElementType))
                {
                case TypeCode.String: return(CreateArray((string[])value));

                case TypeCode.UInt16: return(CreateArray((ushort[])value));

                case TypeCode.UInt32: return(CreateArray((uint[])value));

                case TypeCode.UInt64: return(CreateArray((ulong[])value));

                case TypeCode.Int16: return(CreateArray((short[])value));

                case TypeCode.Int32: return(CreateArray((int[])value));

                case TypeCode.Int64: return(CreateArray((long[])value));

                case TypeCode.Single: return(CreateArray((float[])value));

                case TypeCode.Double: return(CreateArray((double[])value));

                default: return(ReadArray((IEnumerable)value));
                }
            }
            else if (value is IEnumerable)
            {
                if (type.IsList && type.ElementType != null)
                {
                    switch (Type.GetTypeCode(type.ElementType))
                    {
                    case TypeCode.String: return(CreateList <string>(value));

                    case TypeCode.UInt16: return(CreateList <ushort>(value));

                    case TypeCode.UInt32: return(CreateList <uint>(value));

                    case TypeCode.UInt64: return(CreateList <ulong>(value));

                    case TypeCode.Int16: return(CreateList <short>(value));

                    case TypeCode.Int32: return(CreateList <int>(value));

                    case TypeCode.Int64: return(CreateList <long>(value));

                    case TypeCode.Single: return(CreateList <float>(value));

                    case TypeCode.Double: return(CreateList <double>(value));
                    }
                }

                return(ReadArray((IEnumerable)value));
            }
            else
            {
                // Complex object
                return(ReadObject(value));
            }
        }