Created
May 21, 2014 16:36
-
-
Save kzu/abb7d77e34734834d76c to your computer and use it in GitHub Desktop.
Json.NET Extensibility Example
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
namespace JsonExtensibility | |
{ | |
public class JsonTests | |
{ | |
[Fact] | |
public void when_serializing_itask_then_can_customize_properties () | |
{ | |
var serializer = new JsonSerializer { | |
Formatting = Formatting.Indented, | |
}; | |
var task = new MyTask { | |
InputScalar = "Scalar", | |
InputSingle = new TaskItem ("Foo.cs", new Dictionary<string, string> { { "Key", "Value" } }), | |
InputMany = new ITaskItem[] | |
{ | |
new TaskItem ("Many1.cs", new Dictionary<string, string> { { "Key", "Value" } }), | |
new TaskItem ("Many2.cs", new Dictionary<string, string> { { "Key", "Value" } }), | |
} | |
}; | |
serializer.ContractResolver = new TaskContractResolver (); | |
serializer.Converters.Add (new TaskItemConverter ()); | |
var builder = Serialize (serializer, task); | |
Console.WriteLine (builder.ToString ()); | |
var deserialized = (MyTask)serializer.Deserialize (new JsonTextReader (new StringReader (builder.ToString ())), typeof (MyTask)); | |
Assert.Equal (task.InputScalar, deserialized.InputScalar); | |
Assert.Equal (task.InputSingle.ItemSpec, deserialized.InputSingle.ItemSpec); | |
Assert.Equal (task.InputMany.Count (), deserialized.InputMany.Count ()); | |
var rountrip = Serialize (serializer, deserialized); | |
Assert.Equal (builder.ToString (), rountrip.ToString ()); | |
} | |
private static StringBuilder Serialize (JsonSerializer serializer, MyTask task) | |
{ | |
var builder = new StringBuilder (); | |
using (var stringWriter = new StringWriter (builder)) | |
using (var jsonWriter = new JsonTextWriter (stringWriter)) { | |
serializer.Serialize (jsonWriter, task); | |
} | |
return builder; | |
} | |
public class TaskContractResolver : DefaultContractResolver | |
{ | |
protected override JsonObjectContract CreateObjectContract (Type objectType) | |
{ | |
var contract = base.CreateObjectContract (objectType); | |
if (typeof (Task).IsAssignableFrom (objectType)) { | |
foreach (var property in contract.Properties.Where (x => x.DeclaringType != objectType).ToArray ()) { | |
contract.Properties.Remove (property); | |
} | |
} | |
return contract; | |
} | |
} | |
public class TaskItemConverter : JsonConverter | |
{ | |
public override bool CanConvert (Type objectType) | |
{ | |
return typeof (ITaskItem).IsAssignableFrom (objectType); | |
} | |
public override object ReadJson (JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |
{ | |
return serializer.Deserialize<SerializableTaskItem> (reader).ToTaskItem (); | |
} | |
public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer) | |
{ | |
var item = (ITaskItem)value; | |
serializer.Serialize (writer, new SerializableTaskItem (item)); | |
} | |
} | |
public class SerializableTaskItem | |
{ | |
public SerializableTaskItem () | |
{ | |
} | |
public SerializableTaskItem (ITaskItem item) | |
{ | |
this.ItemSpec = item.ItemSpec; | |
this.Metadata = item.CloneCustomMetadata (); | |
} | |
public ITaskItem ToTaskItem () | |
{ | |
return new TaskItem (this.ItemSpec, this.Metadata); | |
} | |
public string ItemSpec { get; set; } | |
public IDictionary Metadata { get; set; } | |
} | |
} | |
public class MyTask : Task | |
{ | |
public string InputScalar { get; set; } | |
public ITaskItem InputSingle { get; set; } | |
public ITaskItem[] InputMany { get; set; } | |
public override bool Execute () | |
{ | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment