Pavel Voronin Pavel Voronin - 11 months ago 54
JSON Question

How to add types information to JSON on serialization?

Angular requires

objects in many places whereas JSON contains string representation of the date.

I want to add an array of properties which contain date values:

class Foo
public int IntProp {get;set;}
public DateTime? Prop1 {get;set;}
public DateTime Prop2 {get;set;}
public Bar Bar {set;set;}

class Bar
public DateTime Prop {get;set;}
public IEnumerable<DateTime?> Dates {get;set;}

Foo should then be serialized like this:

"IntProp": 1,
"Prop1": "...",
"Prop2": "...",
"Bar": {
"Prop": "..."

"<Dates>": [ "Prop1", "Prop2", "Bar.Prop", "Bar.Dates"]

This allows me to automatically convert strings to date objects at the client side without testing every property whether it is convertible to
like it is described in this question.

I can collect the paths of date properties, but have no idea how to add populated array to the root.

dbc dbc
Answer Source

You could convert to an intermediate JObject and add the property there. For instance, given the following converter:

public class PathLoggingDateTimeConverter : IsoDateTimeConverter
    public const string DatePathPropertyName = "<Dates>";

    readonly List<string> paths = new List<string>();

    public override bool CanConvert(Type objectType)
        if (!base.CanConvert(objectType))
            return false;
        // Not for DateTimeOffset
        return objectType == typeof(DateTime) || objectType == typeof(DateTime?);

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        base.WriteJson(writer, value, serializer);
        if (value != null)

    public IList<string> Paths { get { return paths; } }

You can do:

        var root = new Foo
            IntProp = 101,
            Prop1 = DateTime.Today.ToUniversalTime(),
            Prop2 = DateTime.Today.ToUniversalTime(),
            Bar = new Bar
                Prop = DateTime.Today.ToUniversalTime(),
                Dates = new List<DateTime?> { null, DateTime.Today.ToUniversalTime() },

        var converter = new PathLoggingDateTimeConverter();
        var settings = new JsonSerializerSettings { Converters = new[] { converter } };
        var obj = JObject.FromObject(root, JsonSerializer.CreateDefault(settings));
        obj[PathLoggingDateTimeConverter.DatePathPropertyName] = JToken.FromObject(converter.Paths);


And the result is:

  "IntProp": 101,
  "Prop1": "2016-10-25T04:00:00Z",
  "Prop2": "2016-10-25T04:00:00Z",
  "Bar": {
    "Prop": "2016-10-25T04:00:00Z",
    "Dates": [
  "<Dates>": [