【问题标题】:How do I customize JSON serialization?如何自定义 JSON 序列化?
【发布时间】:2013-02-28 16:19:12
【问题描述】:

目前我有一个看起来像这样的类:

public class TestSerilizer
{
    public int IntValue;
    public DateTime DTValue;
}

还有一个控制器,该控制器将序列化为 JSON 的类返回,如下所示:

public ActionResult TestJson()
{
    TestSerilizer testDT = new TestSerilizer();
    return Json(testDT);
}

众所周知,这会在 JSON 中生成类似于 /Date(123456)/ 的日期,这不太理想。出于我的目的,我希望能够添加一个属性,该属性将以对我的观点有意义的方式格式化我的日期。理想情况下,我想将我的视图模型更改为如下所示:

public class TestSerilizer
{
    public int IntValue;
    [JSONDateFormatter("hh:mm tt")]
    public DateTime DTValue;
}

这将生成带有格式化日期的 JSON 数据。有没有办法劫持 JSON 序列化来做类似的事情?应该注意的是,这是一个大型代码库,它同时具有这种隐式 JSON 序列化和显式使用 JavaScriptSerializer 类,所以我更喜欢一种适用于这两种情况的方法,但我知道这可能是不可能的。

【问题讨论】:

  • 日期在 json 中尤为突出。我通常将它们视为字符串并尝试以 javascript 不会尝试解释或管理它们的方式发送它们

标签: c# json serialization asp.net-mvc-4


【解决方案1】:

这通常是我管理对象日期序列化的方式。请注意,这使用了 dataMember 属性,因为它需要被二进制和 json 序列化:

[DataContract]
[Serializable]
public class YourClass
{
        [DataMember]
        private long timeStampLong;


        [IgnoreDataMember]
        public DateTime TimeStamp
        {
            get { return new DateTime(timeStampLong); }
            set { timeStampLong = value.Ticks; }
        }
}

现在这可能不会使日期时间在 json 中可读,但它会使其保持一致。不同的 json 库处理序列化日期时间的方式不同,因此您希望能够强制它们都以相同的方式序列化。

编辑:请注意,这不是 C# 属性意义上的第二个属性,而只是该属性的基础字段。您可以将基础字段改为字符串,并且该基础字段永远不会暴露在对象之外。由于IgnoreDataMember,您仍然只序列化一个值。

Edit2:当有人需要实现此功能时,添加了类声明以获得更完整的答案。

编辑:对于更完整的示例,我想我会包括我使用过的另一个选项(以字符串作为支持字段)

    /// <summary>
    /// Representations of the TimeStamp used for serialization
    /// </summary>
    [DataMember(Name = "TimeStamp")]
    private String timeStamp;

    /// <summary>
    /// timestamp when the request is sent
    /// </summary>
    [IgnoreDataMember]
    public DateTime TimeStamp
    {
        get { return DateTime.Parse(timeStamp, null, DateTimeStyles.RoundtripKind); }
        set { timeStamp = value.ToUniversalTime().ToString("o"); }
    }

【讨论】:

  • 这很漂亮...一定要试试
  • 我们有一个需要支持多个 json 库的系统(因为我们不知道我们的客户端将使用哪个)所以这样无论您使用的是 .net 序列化程序、newtonsoft 还是其他一些其他 json 序列化器它总是只会序列化 long 值。
  • 我希望避免拥有第二处房产,但看起来越来越不可能了。
  • 请注意,这不是 C# 属性意义上的第二个属性,而只是该属性的基础字段。您也可以将基础字段设为字符串,并且该基础字段永远不会暴露在对象之外。由于IgnoreDataMember,您仍然只序列化一个值。(也添加了这个来回答,所以人们不必通过 cmets 进行挖掘)
【解决方案2】:

正如@jzworkman 所指出的,该响应中的技术大纲是如何控制内部 DateTime 值如何被序列化。我坚持始终使用基于字符串的格式,该格式几乎可以被其他任何东西可靠地解析。如果可能的话,我坚持使用可以正确处理时区映射的 ISO 8601 格式。在 C# 中,您可以使用 myDateTimeValue.ToString("o") 获取 ISO 8601 中 DateTime 的字符串。

Wikipedia article on ISO 8601

【讨论】:

    猜你喜欢
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多