Custom Json Converter For Ember Data relation with WebApi2

Currently, I am writing WebAPI for Ember Front-end. There is a great requirement in Ember to send relationship of any object with their ID only.

class Address 
{
 public int id;
 public string location;
 public string postcode;
}
class Employee 
{
   public string Name {get;set;}
   public ICollection<Address> Addresses { get; set; }
}

 

The default behavior of Json.NET Serializer is it will send Employee record with collection of Address that has all fields i.e. location, postcode, id.

{
 "Name": "Amit"
 "Addresses" : 
 [
 {"id" : 1, "location" : "XX", "postcode" : "XX" },
 {"id" : 2, "location" : "XX", "postcode" : "XX" }
 ]
}

I want to modify JSON.NET so that when I am serializing a Model from my API it sends only an array of IDs for a composite Collection object.

i.e. The above serialization should look like:

{
"Name": 'Amit',
"Addresss" : [1,2]
}

You can get the result you want using a custom JsonConverter such as this:

/// <summary>
 /// Defines the custom JSON Converter of collection type that serialize collection to an array of ID for Ember.
 /// </summary>
 public class IDWriteListConverter : JsonConverter
 {
 /// <summary>
 /// Define the property name that is define in the collection type.
 /// </summary>
 private readonly string keyname = "ID";
/// <summary>
 /// It is write only convertor and it cannot be read back.
 /// </summary>
 public override bool CanRead
 {
 get { return false; }
 }
/// <summary>
 /// Validate that this conversion can be applied on IEnumerable type only.
 /// </summary>
 /// <param name="objectType">type of object</param>
 /// <returns>Validated value in boolean</returns>
 public override bool CanConvert(Type objectType)
 {
 return typeof(IEnumerable).IsAssignableFrom(objectType)
 && objectType != typeof(string);
 }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
 {
 throw new NotImplementedException();
 }
/// <summary>
 /// Write JSON data from IEnumerable to Array.
 /// </summary>
 /// <param name="writer">JSON Writer</param>
 /// <param name="value">Value of an object</param>
 /// <param name="serializer">JSON Serializer object</param>
 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
 {
 JArray array = new JArray();
 foreach (object item in (IEnumerable)value)
 {
 PropertyInfo idProp = item.GetType().GetProperty(this.GetKeyName());
 if (idProp != null && idProp.CanRead)
 {
 array.Add(JToken.FromObject(idProp.GetValue(item, null)));
 }
 }
array.WriteTo(writer);
 }
public virtual string GetKeyName()
 {
 return keyname;
 }
 }

In your model, wherever you have a collection of something where you only want the IDs, decorate the collection property with a [JsonConverter] attribute specifying the custom converter. For example:

class Employee
{
 public string Name { get; set; }
[JsonConverter(typeof(IDWriteListConverter))]
 public ICollection<Address> Addresses { get; set; }
}

When the collection gets serialized, the converter will be used, and only the ID values will be written out. Demo:

class Program
{
 static void Main(string[] args)
 {
 Employee emp = new Employee
 {
 name = "Joe",
 Addresses = new List<Address>
 {
 new Address { id = 1, location = "foo", postcode = "bar" },
 new Address { id = 2, location = "baz", postcode = "quux" }
 }
 };
string json = JsonConvert.SerializeObject(emp);
Console.WriteLine(json);
}
}

Output:

{"name":"Joe","Addresses":[1,2]}