Created
February 20, 2012 10:17
-
-
Save philipmat/1868672 to your computer and use it in GitHub Desktop.
JSON Entity Converter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
var co = new Company { Id = 1, Name = "Moof Inc." }; | |
var clarus = new Contact { Id = 1, Name = "Clarus" }; | |
var mark = new Contact { Id = 2, Name = "Mark" }; | |
co.AddContact(clarus); | |
co.AddContact(mark); | |
co.MainContact = clarus; | |
// Attempt #1: Straight up, no converter | |
// var serializer1 = new JavaScriptSerializer(); | |
// serializer1.Serialize(co).Dump(); | |
// => InvalidOperationException: A circular reference was detected while serializing an object of type 'UserQuery+Company'. | |
// Attempt #2: Converter handles all Entities | |
var converter2 = new EntityConverter(); | |
var serializer2 = new JavaScriptSerializer(); | |
serializer2.RegisterConverters(new[] { converter2 }); | |
serializer2.Serialize(co).Dump(); | |
// => {"Name":"Moof Inc.","Contacts":[{"Name":"Clarus","WorksFor":1,"Id":1},{"Name":"Mark","WorksFor":1,"Id":2}],"MainContact":1,"Id":1} | |
// Attempt #3: Converter handles only contacts | |
var converter3 = new EntityConverter(new[] { typeof(Contact) }); | |
var serializer3 = new JavaScriptSerializer(); | |
serializer3.RegisterConverters(new[] { converter3 }); | |
serializer3.Serialize(co).Dump(); | |
// => {"Name":"Moof Inc.","Contacts":[{"Name":"Clarus","WorksFor":1,"Id":1},{"Name":"Mark","WorksFor":1,"Id":2}],"MainContact":{"Name":"Clarus","WorksFor":1,"Id":1},"Id":1} | |
// Attempt #4: Converter with custom output for entities. | |
var converter4 = new EntityConverter(new[] { typeof(Contact) }, en => new ReducedEntity(en)); | |
var serializer4 = new JavaScriptSerializer(); | |
serializer4.RegisterConverters(new[] { converter4 }); | |
serializer4.Serialize(co).Dump(); | |
// => {"Name":"Moof Inc.","Contacts":[{"Name":"Clarus","WorksFor":{"TypeName":"Company","Id":1},"Id":1},{"Name":"Mark","WorksFor":{"TypeName":"Company","Id":1},"Id":2}],"MainContact":{"Name":"Clarus","WorksFor":{"TypeName":"Company","Id":1},"Id":1},"Id":1} | |
} | |
// Define other methods and classes here | |
public class Entity { | |
public int Id { get; set; } | |
} | |
public class Company : Entity { | |
public string Name { get; set; } | |
public IEnumerable<Contact> Contacts { get { return _contacts; } } | |
public Contact MainContact { get; set; } | |
public void AddContact(Contact aContact) { | |
if (_contacts.Contains(aContact)) throw new ArgumentException("Contact already exists in the list."); | |
aContact.WorksFor = this; | |
_contacts.Add(aContact); | |
} | |
private List<Contact> _contacts = new List<Contact>(); | |
} | |
public class Contact : Entity { | |
public string Name { get; set; } | |
// public string Address { get; set; } | |
public Company WorksFor { get; set; } | |
} | |
public class EntityConverter : JavaScriptConverter { | |
private IEnumerable<Type> _supportedTypes; | |
private Func<Entity, object> _reducer; | |
public EntityConverter() : this(new[] { typeof(Entity) }) {} | |
public EntityConverter(IEnumerable<Type> supportedTypes, Func<Entity, object> reducer = null) { | |
_supportedTypes = supportedTypes.DefaultIfEmpty(typeof(Entity)); | |
_reducer = reducer ?? (en => en.Id); | |
} | |
public override IEnumerable<Type> SupportedTypes { get { return _supportedTypes; } } | |
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { | |
var ret = new Dictionary<string, object>(); | |
if (obj == null) return ret; | |
string name; object value; | |
var props = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty); | |
foreach (PropertyInfo prop in props) { | |
name = prop.Name; | |
value = prop.GetValue(obj, null); | |
if (value != null && typeof(Entity).IsAssignableFrom(prop.PropertyType)) | |
ret.Add(name, _reducer((Entity) value)); | |
else | |
ret.Add(name, value); | |
} | |
return ret; | |
} | |
public override object Deserialize(IDictionary<string, object> obj, Type type, JavaScriptSerializer serializer) { | |
throw new NotImplementedException(); | |
} | |
} | |
public class ReducedEntity { | |
public ReducedEntity(Entity anEntity) { | |
TypeName = anEntity.GetType().Name; | |
Id = anEntity.Id; | |
} | |
public string TypeName { get; private set; } | |
public int Id { get; private set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment