WCFのDateTimeのデフォルトのJSONシリアル化/逆シリアル化を変更する方法はありますか?
現在、DateTimeは/Date(1372252162657+0200)/
形式にシリアル化されていますが、これは問題ないはずですが、サーバーがUTCでない場合(変更できない)、問題が発生しています。
このサービスで処理されているすべての日付/時刻データはUTC形式です。サーバーがUTCにある場合、すべてが機能します。ただし、ステージング/製品環境はGMT + 1(パリ)に設定され、シリアライザは日付/時刻がGMT + 1であると想定し、属性Kind
を完全に無視します。したがって、DateTime.SetKind()
を呼び出してUTCに設定しても、期待どおりに機能しません。実際、シリアル化された時間は1時間遅れます。
私は双方向の日付会話を行うこともできます(逆シリアル化するときにも同じ仮定を行うため、常にGMT + 1です)日付の会話:UTCとサーバー時間の間のやり取りですが、これは面倒です。だから私は多分私は単にデフォルトのシリアル化動作をオーバーライドできると思いました。
はい、これは「Message Formatters」という概念を使用して行うことができます
ただし、メッセージフォーマッタは、スタックオーバーフローについてここで説明するのは難しく、範囲外です。参照できます WCF Extensibility:Message Formatters
これを台無しにしたくない場合は、ハックを利用できます。
各メソッドの戻り値の型を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は、シリアル化のためにストリーム出力をスキップし、そのままクライアントに渡します。
答えが出たらいいのに。
tdelepineのコードスニペットを拡張するために、ここで私が使用したコード:
私のWCF JSONサービスでは、(null可能)DateTime値があり、サービスがより読みやすい形式で日付を返すようにしたいので、iPhoneアプリで日付を解釈できます。
いくつかの変更を適用した後のJSONは次のようになります。
WCFがDateTimesを書き込むデフォルトの方法であるUpdateDateOriginal
フィールドと、以下のコードを使用して作成したより親しみやすい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);
}
実際、DateTime
の値をISO8601形式で返す方が便利な場合があります。例えば:
UpdateTime: "2014-08-24T13:02:32",
これを行うには、上記のコードを使用するだけですが、両方の場所で文字列"MMM/dd/yyyy HH:mm"
を"s"
に変更します。
また、DateTime値がUTCに格納されているが、WCFサービスがユーザーのローカルタイムゾーンで値を返すようにしたい場合は、ここで私のヒントに従うことができます。
いくつかの簡単な例で、人生は簡単ではありません!
あなたはあなたのjsonオブジェクト定義でこの回避策を使うことができます
[IgnoreDataMember]
public DateTime dateObject;
public string dateCustomSerialize
{
get {
//Custom get
}
set {
//Custom set
}
}
評価者には、カスタム形式のシリアル化を配置します
これでタイムゾーンの問題が解決するわけではありませんが、WCF、ティック、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); } }
1つの方法は、メッセージフォーマッタを使用して、デフォルトのDataContractSerializer
を WCF Extensibility – Message Formatters で説明されているように変更することです。
もう1つのオプションは、オブジェクトをストリームにロードする拡張メソッドを記述して、オブジェクトに必要なシリアライザを適用することです。これを行う方法の詳細については、受け入れ済みの回答 WCF 4のデフォルトのJSONシリアライザーをJSON.NETに置き換える を参照してください。