internal IEnumerable <KeyValuePair <string, JsonNode> > ReadProperties(object instance)
        {
            var contract = JsonModelCache.Get(instance.GetType());

            foreach (var member in contract.Members)
            {
                string name = member.Name;

                if (options.PropertyNameTransformer != null)
                {
                    name = options.PropertyNameTransformer.Invoke(name);
                }

                // Skip the field if it's not included
                if ((depth == 1 && !options.IsIncluded(name)))
                {
                    continue;
                }

                var value = member.GetValue(instance);

                if (!member.EmitDefaultValue && (value == null || (member.IsList && ((IList)value).Count == 0) || value.Equals(member.DefaultValue)))
                {
                    continue;
                }
                else if (options.IgnoreNullValues && value == null) // Ignore null values
                {
                    continue;
                }

                // Transform the value if there is one
                if (options.Transformations != null)
                {
                    var transform = options.GetTransformation(name);

                    if (transform != null)
                    {
                        value = transform.Transformer(value);
                    }
                }

                yield return(new KeyValuePair <string, JsonNode>(name, ReadValue(member.TypeDetails, value)));
            }
        }
        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));
            }
        }