C# 在 WCF 中更改默认日期序列化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18511147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 12:26:43  来源:igfitidea点击:

Change default date serialization in WCF

c#jsonwcfdatetimeserialization

提问by Mel

Is there anyway to change the default JSON serialization/deserialization of DateTime in WCF?

无论如何要更改 WCF 中 DateTime 的默认 JSON 序列化/反序列化?

Currently, DateTime are serialized into the /Date(1372252162657+0200)/format, which should've been fine but I'm running into issues when my server is not in UTC (which I can't change).

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

All date/time data that is being processed by this service is in UTC format. Everything works when the server is in UTC. However, the staging/prod environments are set to GMT+1(Paris) and the serializer is assuming that the dates/times are in GMT+1, completely ignoring the attribute Kind. So as you'd expect calling DateTime.SetKind()and setting it to UTC will not work. In effect, the serialized times are delayed by an hour.

此服务正在处理的所有日期/时间数据均采用 UTC 格式。当服务器处于 UTC 时,一切正常。但是,暂存/生产环境设置为 GMT+1(Paris) 并且序列化程序假设日期/时间在 GMT+1,完全忽略属性Kind。因此,正如您所期望的那样,调用DateTime.SetKind()并将其设置为 UTC 将不起作用。实际上,序列化时间延迟了一个小时。

I can either do two-way date conversations (it also makes the same assumption when deserializing so its always GMT+1) conversation of dates: UTC to/from server time, but this is to tedious. So I thought maybe I could just override the default serialization behavior.

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

采纳答案by Ronak Patel

Yes, this can be done using the concept called "Message Formatters"

是的,这可以使用称为“消息格式器”的概念来完成

But Message Formatter would be tough and out of scope to explain here on stack overflow. You can refere WCF Extensibility : Message Formatters

但是 Message Formatter 将很难在这里解释堆栈溢出。您可以参考WCF Extensibility : Message Formatters

If you don't want mess up with this then an hack is available.

如果您不想弄乱这个,那么可以使用 hack。

Set the return type of each method to Stream.

将每个方法的返回类型设置为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()));
        }

here ToJson() is my own extension method which converts object into json string using NewtonSoft library.

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

WCF will skip the stream output for serializing and will pass it to your client as it is.

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

I hope you got your answer.

我希望你得到你的答案。

回答by Karl Anderson

One way is to use a message formatter to change the default DataContractSerializeras described in WCF Extensibility – Message Formatters.

一种方法是使用消息格式化程序更改默认值DataContractSerializer,如WCF 扩展性 - 消息格式化程序中所述

Another option is to write an extension method that loads your object into a stream and then you can apply whatever serializer you want to the object. See the accepted answer for Replace default JSON serializer in WCF 4 to JSON.NETfor details on how to do this.

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

回答by tdelepine

you can use this workaround, In your json object definition

您可以使用此解决方法,在您的 json 对象定义中

[IgnoreDataMember]
public DateTime dateObject;

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

In assessor place your custom format serialisation

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

回答by Mike Gledhill

Just to expand on tdelepine's code snippet, here the code I've used:

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

In my WCF JSON Service, I had a (nullable) DateTime value, and wanted my service to return the date in a more readable format, so my iPhone app would be able to interpret it.

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

Here's what my JSON looked like, after applying a few changes:

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

enter image description here

在此处输入图片说明

Notice the UpdateDateOriginalfield, which is the default way that WCF writes DateTimes, and the friendlier UpdateDatefield, which I created using the code below.

请注意该UpdateDateOriginal字段,这是 WCF 编写 DateTimes 的默认方式,以及UpdateDate我使用以下代码创建的更友好的字段。

My original lines looked like this:

我原来的台词是这样的:

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

... and here are the lines to create the new friendlier UpdateDateJSON value.

...这里是创建新的更友好的UpdateDateJSON 值的行。

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

Actually, you may find it more useful to return DateTimevalues in ISO8601 format. For example:

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

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

To do this, simply use my code above, but change the string "MMM/dd/yyyy HH:mm"to "s"in both places.

要做到这一点,只需使用我上面的代码,但是字符串更改"MMM/dd/yyyy HH:mm""s"这两个地方。

And, if your DateTime values are stored in UTC, but you wanted your WCF services to return the values in the user's local timezone, you can follow my tips here:

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

Get DateTime in users local timezone

获取用户本地时区的日期时间

Isn't life easier, with a few simple examples !

生活不是更轻松,举几个简单的例子!

回答by Robotron

This does not solve your issue of timezones, but I'll post it here for others who are battling it out with WCF, ticks and DateTime.

这并不能解决您的时区问题,但我会在此处将其发布给正在与 WCF、滴答声和 DateTime 进行斗争的其他人。

If you don't want ticks, but human-readable time format, you can do it by introducing an additional stringproperty. Then it's a matter of fiddling with the DateTimebefore turning the value into a string.

如果你不想要刻度,而是人类可读的时间格式,你可以通过引入一个额外的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); } }