Newtonsoft.Json, Linq and KnockoutJs
Here is example of defining custom JsonConverters, which allow control way of serializing objects.
In this code objects are serialized into knockout ko.observable and ko.observableArray.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
class Program
{
static void Main(string[] args)
{
// Dummy data for example, here we have numeric, string and collection values
var data = new[] {
new { id = 1, name = "one", nums = new[] {1,2,3} },
new { id = 2, name = "two", nums = new[] {1,2,3} }
};
// Example of linq, notice how we are wrapping variables with ko.observable and ko.observableArray
var items = from i in data
select new
{
id = new KO.Observable(i.id),
name = new KO.Observable(i.name),
nums = new KO.ObservableArray(i.nums),
cusom = new KO.Wrapped(i, "new SubModel(", ")"),
person = new Person() { Name = "Alex", Age = 29, Phones = new List<string>() { "phone1", "phone2" } },
};
Console.WriteLine(KO.JsonConvert.SerializeObject(items));
Console.ReadKey();
}
public class Person
{
[Newtonsoft.Json.JsonConverter(typeof(KO.ObservableConverter))]
public string Name { get; set; }
[Newtonsoft.Json.JsonConverter(typeof(KO.ObservableConverter))]
public int Age { get; set; }
[Newtonsoft.Json.JsonConverter(typeof(KO.ObservableArrayConverter))]
public List<string> Phones { get; set; }
}
}
}
namespace KO
{
public class Wrapped
{
public object Value { get; set; }
public string Before { get; set; }
public string After { get; set; }
public Wrapped(object value = null, string before = null, string after = null)
{
Value = value;
Before = before;
After = after;
}
}
public class Observable : Wrapped
{
public Observable(object value = null) : base(value, "ko.observable(", ")") { }
}
public class ObservableArray : Wrapped
{
public ObservableArray(object value = null) : base(value, "ko.observableArray(", ")") { }
}
public class WrappedConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (typeof(Wrapped) == objectType || typeof(Wrapped) == objectType.BaseType);
}
public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
{
return existingValue;
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
{
writer.WriteRawValue((value as Wrapped).Before + Newtonsoft.Json.JsonConvert.SerializeObject((value as Wrapped).Value, Newtonsoft.Json.Formatting.None) + (value as Wrapped).After);
}
}
public class ObservableConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
{
return existingValue;
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
{
writer.WriteRawValue("ko.observable(" + Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None) + ")");
}
}
public class ObservableArrayConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
{
return existingValue;
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
{
writer.WriteRawValue("ko.observableArray(" + Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None) + ")");
}
}
public static class JsonConvert
{
static WrappedConverter wrappedConverter = new WrappedConverter();
public static string SerializeObject(object value)
{
return Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.Indented, wrappedConverter);
}
}
}
This code will produce output like this one: