Method 1: Use "Proxy" Properties
Put [ScriptIgnore]
attributes on your DateTime
properties and implement proxy properties that get the date value as a string. The properties with [ScriptIgnore]
will be skipped by JavaScriptSerializer
and the proxy properties will be emitted. For example:
[ScriptIgnore]
public DateTime DateValue { get; set; }
public string DateValueJS
{
get { return DateValue.ToString("g"); }
}
Method 2: Use CustomConverters with JavaScriptSerializer
Use the CustomConverters support that's built into JavaScriptSerializer
to register your own class for handling the serialization of particular types. For example:
public class DateJsonConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get { return new Type[] { typeof(DateTime) }; }
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
return new Dictionary<string, object>()
{
{ "Value", ((DateTime)obj).ToString("g") }
};
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
throw new NotSupportedException();
}
}
And you use this custom converter like this:
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new DateJsonConverter() });
Date values will be serialized by this class into: {"Dt":{"Value":"6/11/2013 5:36 PM"}}
Method 3: Use Reflection to transparently format DateTime
You can use reflection to transparently convert DateTime
values into string
values when the value is being serialized. For example:
private static object FormatDateTime(object x)
{
if (x == null || x is IEnumerable)
return x;
var t = x.GetType();
if (t == typeof(DateTime))
return ((DateTime)x).ToString("g");
if (t.IsPrimitive)
return x;
var result = new Dictionary<string, object>();
foreach (var prop in t.GetProperties())
{
// Skip properties with ScriptIgnoreAttribute
if (prop.GetCustomAttributes(typeof(ScriptIgnoreAttribute), true).Any())
continue;
result[prop.Name] = FormatDateTime(prop.GetValue(x, null));
}
return result;
}
This method can be used in your Select
statement to convert the object values into a Dictionary
that JavaScriptSerializer
can use to emit the JSON. For example:
var value = new[] { new { Dt = DateTime.Now, Childs = new[] { 1, 2, 3 } } };
serializer.Serialize(value.Select(x => FormatDateTime(x)))
Will emit [{"Dt":"6/12/2013 3:27 PM","Childs":[1,2,3]}]