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

bkhjykvo  于 2023-04-22  发布在  其他
关注(0)|答案(5)|浏览(112)

是否有办法更改WCF中DateTime的默认JSON序列化/反序列化?
目前,DateTime被序列化为/Date(1372252162657+0200)/,这应该没问题,但当我的服务器不在UTC时(我不能更改),我遇到了问题。
此服务正在处理的所有日期/时间数据都是UTC格式。当服务器处于UTC时,一切都正常。但是,staging/prod环境设置为GMT+1(巴黎)并且序列化器假设日期/时间是GMT+1,完全忽略属性Kind。因此,正如您所期望的那样,调用DateTime.SetKind()并将其设置为UTC将不起作用。实际上,序列化的时间被延迟一小时。
我可以进行双向日期对话(在反序列化时也做了同样的假设,所以总是GMT+1)日期对话:UTC到/从服务器时间,但这太乏味了。所以我想也许我可以覆盖默认的序列化行为。

soat7uwm

soat7uwm1#

只是为了扩展 tdelepine 的代码片段,这里是我使用的代码:
在我的WCF JSON服务中,我有一个(可空的)DateTime值,并希望我的服务以更可读的格式返回日期,这样我的iPhone应用程序就能够解释它。
下面是我的JSON在应用一些更改后的样子:

请注意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);
}

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

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

要做到这一点,只需使用我上面的代码,但在两个地方都将字符串"MMM/dd/yyyy HH:mm"更改为"s"
而且,如果你的DateTime值存储在UTC中,但你希望你的WCF服务返回用户本地时区的值,你可以按照我的提示在这里:
Get DateTime in users local timezone
生活不是更简单吗,举几个简单的例子!

7xzttuei

7xzttuei2#

你可以在你的json对象定义中使用这个解决方法

[IgnoreDataMember]
public DateTime dateObject;

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

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

nr7wwzry

nr7wwzry3#

可以,可以使用名为“消息格式”的概念来完成
但是Message Formatter会很坚韧,并且超出了在这里解释堆栈溢出的范围。
如果你不想搞砸了这一点,然后黑客是可用的。
将每个方法的返回类型设置为Stream。
例如

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将跳过要序列化的流输出,并将其原样传递给客户端。
希望你得到了答案。

z0qdvdin

z0qdvdin4#

这并不能解决你的时区问题,但我会在这里为其他正在与WCF,ticks和DateTime斗争的人发布它。
如果你不想要刻度,而是人类可读的时间格式,你可以通过引入一个额外的string属性来做到这一点。

[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); } }
syqv5f0l

syqv5f0l5#

一种方法是使用消息格式化程序更改默认的DataContractSerializer,如WCF Extensibility – Message Formatters中所述。
另一种选择是编写一个扩展方法,将对象加载到流中,然后您可以将任何想要的序列化程序应用于对象。有关如何做到这一点的详细信息,请参阅Replace default JSON serializer in WCF 4 to JSON.NET的公认答案。

相关问题