更改WCF中的默认日期序列化

时间:2013-08-29 12:33:43

标签: c# json wcf datetime serialization

是否有更改WCF中DateTime的默认JSON序列化/反序列化?

目前,DateTime被序列化为/Date(1372252162657+0200)/格式,应该没问题,但是当我的服务器不是UTC(我无法更改)时,我遇到了问题。

此服务正在处理的所有日期/时间数据均为UTC格式。当服务器使用UTC时,一切正常。但是,staging / prod环境设置为GMT + 1(Paris),序列化器假设日期/时间是GMT + 1,完全忽略属性Kind。因此,您希望调用DateTime.SetKind()并将其设置为UTC将无法正常工作。实际上,序列化时间会延迟一个小时。

我可以进行双向日期对话(在反序列化时也做出相同的假设,因此它的GMT + 1总是)对话的日期:UTC到/从服务器时间,但这是乏味的。所以我想也许我可以覆盖默认的序列化行为。

5 个答案:

答案 0 :(得分:20)

只是为了扩展 tdelepine 的代码段,这里是我使用过的代码:

在我的WCF JSON服务中,我有一个(可为空的)DateTime值,并希望我的服务以更易读的格式返回日期,因此我的iPhone应用程序将能够解释它。

在应用了一些更改之后,这就是我的JSON的样子:

enter image description here

注意UpdateDateOriginal字段,它是WCF写入DateTimes的默认方式,以及我使用下面的代码创建的友好UpdateDate字段。

我的原始线条看起来像这样:

[DataMember]
public DateTime? UpdateDateOriginal { get; set; }

...以下是创建新友好UpdateDate JSON值的行。

[IgnoreDataMember]
public DateTime? UpdateDate { get; set; }

[DataMember(Name = "UpdateDate")]
private string UpdateDateString { get; set; }

[OnSerializing]
void OnSerializing(StreamingContext context)
{
    if (this.UpdateDate == null)
    this.UpdateDateString = "";
    else
    this.UpdateDateString = this.UpdateDate.Value.ToString("MMM/dd/yyyy HH:mm", CultureInfo.InvariantCulture);
}

[OnDeserialized]
void OnDeserializing(StreamingContext context)
{
    if (this.UpdateDateString == null)
    this.UpdateDate = null;
    else
    this.UpdateDate = DateTime.ParseExact(this.UpdateDateString, "MMM/dd/yyyy HH:mm", CultureInfo.InvariantCulture);
}

实际上,您可能会发现以ISO8601格式返回DateTime值更有用。例如:

UpdateTime: "2014-08-24T13:02:32",

要执行此操作,只需使用上面的代码,但在两个位置都将字符串"MMM/dd/yyyy HH:mm"更改为"s"

并且,如果您的DateTime值以UTC格式存储,但您希望WCF服务返回用户本地时区的值,则可以按照我的提示进行操作:

Get DateTime in users local timezone

通过一些简单的例子,生活不容易!

答案 1 :(得分:12)

您可以在json对象定义中使用此变通方法

[IgnoreDataMember]
public DateTime dateObject;

public string dateCustomSerialize
{
 get {
//Custom get
}
set {
//Custom set
}
}

在评估中放置自定义格式序列化

答案 2 :(得分:4)

是的,可以使用名为“邮件格式化程序

的概念来完成

但是Message Formatter很难解决堆栈溢出问题。 你可以参考WCF Extensibility : Message Formatters

如果你不想搞砸这个,那么黑​​客就可以了。

将每个方法的返回类型设置为Stream。

e.g。

        public Stream GetStaticData()
        {
            var objTobeReturned = something;
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
            return new MemoryStream(Encoding.UTF8.GetBytes(objTobeReturned.ToJson()));
        }

这里ToJson()是我自己的扩展方法,它使用NewtonSoft库将对象转换为json字符串。

WCF将跳过用于序列化的流输出,并将其原样传递给您的客户端。

我希望你得到答案。

答案 3 :(得分:0)

一种方法是使用邮件格式化程序更改默认DataContractSerializer,如WCF Extensibility – Message Formatters中所述。

另一种选择是编写一个扩展方法,将对象加载到流中,然后可以将任何所需的序列化程序应用于该对象。有关如何执行此操作的详细信息,请参阅Replace default JSON serializer in WCF 4 to JSON.NET的已接受答案。

答案 4 :(得分:0)

这并不能解决你的时区问题,但是我会在这里发布给其他正在与WCF,ticks和DateTime进行斗争的人。

如果您不想要刻度,但需要人类可读的时间格式,则可以通过引入额外的string属性来实现。然后,在将值转换为字符串之前,需要摆弄DateTime

    [IgnoreDataMember]    // Ignore the original tick date.
    public DateTime LastReminderDate { get { return _lastReminderDate; } set { _lastReminderDate = value; } }
    [DataMember]          // Make sure you have a public or private setter!
    public string LastReminderDateText { get { return _lastReminderDate.ToString(); } set { _lastReminderDate = DateTime.Parse(value); } }