【问题标题】:How to add types information to JSON on serialization?如何在序列化时向 JSON 添加类型信息?
【发布时间】:2016-10-25 11:45:06
【问题描述】:

Angular 在很多地方都需要 Date 对象,而 JSON 包含日期的字符串表示形式。

我想添加一个包含日期值的属性数组:

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 应该像这样被序列化:

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

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

这使我可以在客户端自动将字符串转换为日期对象,而无需测试每个属性是否可转换为Date,就像在此question 中描述的那样。

我可以收集日期属性的路径,但不知道如何将填充数组添加到根。

【问题讨论】:

  • 这里可能有点xy problem。 Json.NET 可以发出多种格式的日期,请参阅here。您希望 DateTIme 属性的 JSON 在不需要额外的 "&lt;Dates&gt;" 属性的情况下看起来如何?
  • @dbc 我更喜欢Date。但我不想离开 ISO 8601。Date 没有特殊的专用格式。我们可以区分字符串、数字、数组和对象,但是日期被格式化为字符串。

标签: angularjs json datetime json.net iso8601


【解决方案1】:

您可以转换为中间 JObject 并在那里添加属性。例如,给定以下转换器:

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

你可以这样做:

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

结果是:

{
  "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]"
  ]
}

【讨论】:

  • 这可能是我真正需要的。明天试试。谢谢。
猜你喜欢
  • 2016-07-16
  • 2021-11-01
  • 2019-09-09
  • 2017-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多