.NETWebAPIシリアル化k_BackingFieldNastiness


86

以下をシリアル化すると:

[Serializable]
public class Error
{

    public string Status { get; set; }
    public string Message { get; set; }
    public string ErrorReferenceCode { get; set; }
    public List<FriendlyError> Errors { get; set; }
}

私はこの嫌な混乱を得る:

<ErrorRootOfstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance"   xmlns="http://schemas.datacontract.org/2004/07/Printmee.Api">
<_x003C_Errors_x003E_k__BackingField>
An exception has occurred. Please contact printmee support
</_x003C_Errors_x003E_k__BackingField>
<_x003C_LookupCode_x003E_k__BackingField>988232ec-6bc9-48f3-8116-7ff7c71302dd</_x003C_LookupCode_x003E_k__BackingField>
</ErrorRootOfstring>

何が得られますか?どうすればこれをきれいにすることができますか?JSON応答にはk_BackingFieldも含まれています


回答:


126

デフォルトでは、WebAPIを使用し[Serializable]たり操作[DataContract]したりする必要はありません。

モデルをそのままにしておくと、WebAPIがすべてのパブリックプロパティをシリアル化します。

何が含まれるかをより細かく制御したい場合にのみ、クラスと[DataContract]それに含まれるプロパティを装飾します[DataMember](DCSとJSON.NETの両方がこれらの属性を表すため)。

何らかの理由で[Serializable]クラスにonが必要な場合(つまり、何らかの理由でメモリストリームにシリアル化する、ディープコピーを実行するなど)、バッキングフィールド名を防ぐために両方の属性を組み合わせて使用​​する必要があります。

[Serializable]
[DataContract]
public class Error
{
    [DataMember]
    public string Status { get; set; }
    [DataMember]
    public string Message { get; set; }
    [DataMember]
    public string ErrorReferenceCode { get; set; }
    [DataMember]
    public List<FriendlyError> Errors { get; set; }
}

6
それだけです-[Serializable]を削除する必要がありました。ありがとう。
ミカ2012

フィリップに感謝します、キャッシュのために属性を保持する必要があります..ところで、私はあなたのブログの熱心なファンです..それを続けてください!
スティーブンパッテン2013年

20
これはひどいです。マイクロソフトはなぜすることはできませんEVERそれは直列化に来るときに正しい何かを?
Chris Marisic 2013年

以下の私自身の答えに示すように、より一般的な解決策があります。
JotaBe 2014年

おそらく、シリアル化の問題は「正しい」の定義であり、誰もが自分のやり方でデータを必要としています。
ルイスフェリペ

94

より一般的な解決策があり[Serializable]ます。属性を無視するようにJsonSerializerを構成できるため、クラスの属性を変更する必要はありません。

この構成変更は、アプリケーションの起動時、つまりGlobal.asaxApplication_Startイベントで行う必要があります。

var serializerSettings =
  GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
var contractResolver =
  (DefaultContractResolver)serializerSettings.ContractResolver;
contractResolver.IgnoreSerializableAttribute = true;

日付をシリアル化するための形式を指定するなど、Jsonシリアル化に他の変更を加えることもできます。

これは、Web APIJSONシリアル化にのみ適用されます。アプリ内の他のシリアル化(Web API XMLシリアル化、MVC JsonResult ...)は、この設定の影響を受けません。


4
このソリューションは、[DataContract]属性と[DataMember]属性をどこにでも追加するよりもはるかに気に入っています。ありがとうございました!!
マークグッド

1
いつも使うべきものではありませんが、これは巧妙なトリックです。モデルを変更したり、コードベースを詳細にリファクタリングしたりする余裕がない厄介な状況を回避するのに役立つ一種のクローバー。
uygar.raf 2015

あなたはこれがそれをするための最良の方法ではないということは正しいです。ただし、場合によっては、リファクタリングは贅沢であるだけでなく、まったく実現可能ではありません。たとえば、コードベースがWCFまたはXMLシリアル化を使用する場合、データコントラクトまたはXMLシリアル化属性が必要です。それを変更することはできません。幸い、JSON.NETは非常に強力です。データコントラクト、XMLシリアル化、および独自の属性をサポートしており、シリアル化にそれらを使用する方法を制御したり、完全に無視したりすることもできます。また、独自の実装を追加することもできます。もちろん、私は属性のないきれいな留め金を保つことを好みます。
JotaBe 2015

これがデフォルトでどのように機能するかです!シリアル化されたストリームで、なぜ私たちはバッキングフィールドのナンセンスを無駄にするのですか?
バイロンホイットロック2015

1
Web APIを使用していて、.netフレームワークのバージョン4をターゲットにしている場合、これを機能させるには、Netwonsoft.Jsonパッケージを更新する必要があります Update-Package Newtonsoft.Json
pblack 2016


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.