18

WCF で DateTime のデフォルトの JSON シリアライゼーション/デシリアライゼーションを変更する方法はありますか?

現在、DateTime は/Date(1372252162657+0200)/形式にシリアル化されています。これは問題ないはずですが、サーバーが UTC でない場合 (変更できません) に問題が発生しています。

このサービスで処理される日付/時刻データはすべて UTC 形式です。サーバーがUTCにある場合、すべてが機能します。ただし、ステージング/本番環境は GMT+1(Paris) に設定されており、シリアライザーは日時が GMT+1 であると想定し、属性を完全に無視していますKind。そのため、呼び出しDateTime.SetKind()て UTC に設定しても機能しません。実際、シリアル化された時間は 1 時間遅れます。

双方向の日付の会話を行うこともできます (逆シリアル化するときも同じ仮定を行うため、常に GMT+1 になります) 日付の会話: UTC とサーバー時間の間ですが、これは面倒です。したがって、デフォルトのシリアライゼーション動作をオーバーライドできるのではないかと考えました。

4

5 に答える 5

23

tdelepineのコード スニペットを拡張するために、ここで使用したコードは次のとおりです。

私の WCF JSON サービスには、(null 許容の) DateTime 値があり、iPhone アプリがそれを解釈できるように、サービスがより読みやすい形式で日付を返すようにしたかったのです。

いくつかの変更を適用した後の JSON は次のようになります。

ここに画像の説明を入力

UpdateDateOriginalWCF が DateTimes を書き込むデフォルトの方法であるフィールドとUpdateDate、以下のコードを使用して作成したわかりやすいフィールドに注意してください。

私の元の行は次のようになりました。

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

... そして、より使いやすい新しい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);
}

DateTime実際には、ISO8601 形式で値を返す方が便利な場合があります。例えば:

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

これを行うには、単純に上記のコードを使用しますが、文字列"MMM/dd/yyyy HH:mm""s"両方の場所で に変更します。

また、DateTime 値が UTC で保存されているが、WCF サービスがユーザーのローカル タイムゾーンで値を返すようにしたい場合は、次のヒントに従ってください。

ユーザーのローカル タイムゾーンで DateTime を取得する

いくつかの簡単な例で、人生はより簡単ではありませんか!

于 2015-01-09T12:46:51.873 に答える
13

この回避策を使用できます.jsonオブジェクト定義で

[IgnoreDataMember]
public DateTime dateObject;

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

アセッサーで、カスタム形式のシリアル化を配置します

于 2013-08-29T12:50:49.887 に答える
4

はい、これは「メッセージフォーマッター」と呼ばれる概念を使用して実行できます

しかし、メッセージ フォーマッターは難しく、スタック オーバーフローについてここで説明する範囲外です。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 はシリアル化のためにストリーム出力をスキップし、そのままクライアントに渡します。

答えが得られたことを願っています。

于 2013-08-29T12:48:21.717 に答える
0

1 つの方法は、メッセージ フォーマッタを使用して既定値を変更することですDataContractSerializer( 「WCF 拡張性 – メッセージ フォーマッタ」を参照) 。

もう 1 つのオプションは、オブジェクトをストリームにロードする拡張メソッドを記述し、必要なシリアライザーをオブジェクトに適用することです。これを行う方法の詳細については、WCF 4 のデフォルトの JSON シリアライザーを JSON.NET に置き換えるの受け入れられた回答を参照してください。

于 2013-08-29T12:49:59.063 に答える