using Newtonsoft.Json.Linq;
using System.Collections;
using System.Collections.Generic;
namespace RecursiveClassProperties
public static class Program
static void Main(string[] args)
var item = CreateDefaultItem(typeof(Order));
Console.WriteLine(JsonSerializer.Serialize(item, new JsonSerializerOptions { WriteIndented = true }));
var json = JsonSerializer.Serialize(item);
var properties = JObject.Parse(json).Flatten();
Console.WriteLine(JsonSerializer.Serialize(properties, new JsonSerializerOptions { WriteIndented = true }));
var formProperties = properties.ToDictionary(x => x.Key, x => new FormResponse(string.Empty));
Console.WriteLine(JsonSerializer.Serialize(formProperties, new JsonSerializerOptions { WriteIndented = true }));
private static object CreateFormItem(Type type, Dictionary<string, FormResponse> formProperties, object result = null)
result = CreateDefaultItem(type);
private static object CreateDefaultItem(Type type, object result = null, object nested = null, bool isBase = false)
void SetProperty(PropertyInfo property, object instance)
if (property.PropertyType == typeof(string)) property.SetValue(instance, string.Empty);
if (property.PropertyType.IsEnum) property.SetValue(instance, 0);
if (property.PropertyType == typeof(Guid)) property.SetValue(instance, Guid.Empty);
result = Activator.CreateInstance(type);
var properties = type.GetProperties();
foreach (var property in properties)
if (!Attribute.IsDefined(property, typeof(FormIgnoreAttribute)) && property.GetSetMethod() is not null)
if (property.PropertyType == typeof(string) || property.PropertyType.IsEnum || property.PropertyType == typeof(Guid))
if (isBase) SetProperty(property, result);
else if (nested is not null && nested.GetType() is not IList && !nested.GetType().IsGenericType) SetProperty(property, nested);
var _nested = default(object);
property.SetValue(result, Activator.CreateInstance(property.PropertyType));
_nested = property.GetValue(result);
property.SetValue(nested, Activator.CreateInstance(property.PropertyType));
_nested = property.GetValue(nested);
CreateDefaultItem(property.PropertyType, result, _nested);
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class FormIgnoreAttribute : Attribute { }
public class FormResponse
public FormResponse(string value) => Value = value;
public string Value { get; set; }
public Guid Id { get; set; }
public Customer Customer { get; set; }
public string Address { get; set; }
public string Postcode { get; set; }
public Test Test { get; set; }
public List<Gender> Genders { get; set; }
public List<string> Tests { get; set; }
public string Value { get; set; }
public List<Gender> Genders { get; set; }
public List<string> Tests { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName => $"{FirstName} {LastName}";
public Gender Gender { get; set; }
public Test Test { get; set; }
public List<Gender> Genders { get; set; }
public List<string> Tests { get; set; }