using Newtonsoft.Json.Linq;
using System.Collections;
using System.Collections.Generic;
public static void Main()
var p1 = new Person(){ Id = 1, FirstName = "Thanh", Roles = new List<string>(){ "Thanh1" }, Group = new Group(){ Name = "Group1" } };
var p2 = new Person(){ Id = 1, LastName = "Truong Duc", Roles = new List<string>(){ "User" }, Group = new Group(){ Id = 1 } };
MergeObject(p1, p2, out p3, typeof(Person));
Console.WriteLine(JsonConvert.SerializeObject(p3));
Console.WriteLine(((Person)p3).FirstName);
private static void MergeObject(object obj1, object obj2, out object obj, Type type)
Console.WriteLine(JsonConvert.SerializeObject(obj1));
Console.WriteLine(JsonConvert.SerializeObject(obj2));
var properties = type.GetProperties().Where(x=>x.CanWrite).ToList();
Console.WriteLine(JsonConvert.SerializeObject(properties.Select(x=>x.PropertyType.FullName).ToList()));
var objDefault = Activator.CreateInstance(type);
obj = Activator.CreateInstance(type);
foreach (var prop in properties)
var propValueDefault = prop.GetValue(objDefault);
var propValue = prop.GetValue(obj1);
Console.WriteLine(typeof(IEnumerable).IsAssignableFrom(prop.PropertyType));
propValue = prop.GetValue(obj2);
}else if(isCollection(prop))
var propObj2Value = prop.GetValue(obj2) as IList;
if (propObj2Value != null)
propValue = propObj2Value;
Console.WriteLine(JsonConvert.SerializeObject(propObj2Value));
Console.WriteLine(JsonConvert.SerializeObject(propValue));
foreach (var item in propObj2Value)
(propValue as IList).Add(item);
Console.WriteLine(JsonConvert.SerializeObject(propValue));
}else if(isChildClass(prop)){
Console.WriteLine("class" + prop.PropertyType);
var propObj2Value = prop.GetValue(obj2);
if(propObj2Value != null){
MergeObject(propValue, propObj2Value, out propValue, prop.PropertyType);
if(propValue.Equals(propValueDefault))
Console.WriteLine("default: " + propValueDefault);
propValue = prop.GetValue(obj2);
prop.SetValue(obj, propValue);
private static bool isCollection(PropertyInfo propertyInfo)
return propertyInfo.PropertyType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(propertyInfo.PropertyType);
private static bool isChildClass(PropertyInfo propertyInfo)
return (propertyInfo.PropertyType.IsClass && !propertyInfo.PropertyType.IsValueType &&
!propertyInfo.PropertyType.IsPrimitive && propertyInfo.PropertyType.FullName != "System.String");
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public List<string> Roles {get;set;}
public Group Group{get;set;}
public string Name{ get;set;}
class PersonConverter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(Person);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
Person person = (Person)value;
JObject result = new JObject();
result.Add("id", person.Id);
result.Add("fullname", (person.FirstName + " " + person.LastName).Trim());
result.Add("address", (person.Address1 + " " + person.Address2).Trim());
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
JObject obj = JObject.Load(reader);
Person person = new Person();
person.Id = (int)obj["id"];
string fullName = (string)obj["fullname"];
string[] parts = fullName.Split(new char[] { ' ' }, 2);
person.FirstName = parts[0];
person.LastName = parts[1];
person.Address1 = (string)obj["address"];