How to add types information to JSON on serialization?

时光怂恿深爱的人放手 提交于 2019-12-12 03:43:23

问题


Angular requires Date 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 Date 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.


回答1:


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)
            paths.Add(writer.Path);
    }

    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);

        Console.WriteLine(obj);

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": [
      null,
      "2016-10-25T04:00:00Z"
    ]
  },
  "<Dates>": [
    "Prop1",
    "Prop2",
    "Bar.Prop",
    "Bar.Dates[1]"
  ]
}


来源:https://stackoverflow.com/questions/40239083/how-to-add-types-information-to-json-on-serialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!