デシリアライズ時にjsonからk__BackingFieldを削除する方法


104

xmlファイルを.net c#オブジェクトにシリアル化した後、返されたjsonでk_BackingFieldを取得しています。

DataContractおよびDataMember属性を.net c#オブジェクトに追加しましたが、json、クライアントエンドには何も表示されません。

[XmlRoot("person")]
[Serializable]
public class LinkedIn
{
    [XmlElement("id")]
    public string ID { get; set; }

    [XmlElement("industry")]
    public string Industry { get; set; }

    [XmlElement("first-name")]
    public string FirstName { get; set; }

    [XmlElement("last-name")]
    public string LastName { get; set; }
    [XmlElement("headline")]
}

返されるjsonの例:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"

回答:


45

クラスがシリアル化で使用できる場合、自動プロパティ構文は実際には推奨されません。バッキングフィールドである理由はコンパイラによって生成されますが、コードがコンパイルされるたびに異なる場合があります。これにより、クラスが変更されていない場合でも(コードを再コンパイルするだけで)非互換性の問題が発生する可能性があります。

この場合、DataMember属性を適用すると問題が解決すると思います。ただし、クラスをシリアル化で使用する必要がある場合は、完全なプロパティ構文を使用することをお勧めします。


Lol、ロングバージョンを実装し、プライベートフィールドをclient.homeに設定しました:Object _fName: "Storefront" _headline: "CEO at StorefrontDoors.NET" _id: "" _industry: ""
スタックの充填は、私が

21
そのdatacontractをクラスの先頭に追加し、datamemberを、興味のある各プロパティに追加します。
スタックをいっぱいにすることは、私が2012年

3
[DataContract]および[DataMember]の@ AlumCloud.Com +1。追加することを忘れないでください:System.Runtime.Serialization
Ian Newland

109

[Serializable]クラスから削除


2
そもそもなぜ[Serializable]が必要だと思ったのかしら。私のXmlシリアル化はなしで動作し、JSONはそれなしで動作します。
Rhyous

11
これはWCFサービスでは機能しません。RESTfulサービスを使用してペイロードを返す場合、[Serializable]を削除してもデータは生成されません。System.Runtime.Serializationを追加し、クラスには[DataContract]、プロパティには[DataMember]を使用します。
イアンニューランド2015

この回答とIanのコメントは両方のケースをカバーしているようです。WCFに対して、またはWCFに対して、それが問題です。
granadaCoder

1
@Rhyous-Web APIでは[Serializable]は必要ありません。WebAPIは、オブジェクトをシリアル化して返すことを前提としてセットアップされているためです(これは基本的にアイデア全体です)-他のC#アプリケーションでは一般的にシリアライズ可能なオブジェクトを区別するためにシリアライズ可能が必要
Jon Story

ありがとう、私は困っていた[Serializable]ので、バッキングフィールドを追加すると役に立ちました。
ohmusama 2017

59

デフォルトのWebApiシリアライザーは、 "__ BackingField:"構文をc#自動プロパティに追加します。これをApp_StartのWebConfigに追加して、探している可能性があるより見栄えの良いjsonを取得します。

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();

3
これで問題が解決しました。オートプロパティは綺麗だと思います。どこでもバッキングフィールドを使用するのはばかげています。多くの混乱を招き、時には混乱を招きます。
Romesh D. Niriella 2016年

これでうまくいきました。私の場合、WCFおよびASMX Webサービスで既に使用されている既存のクラスがあったため、新しいWebAPIプロジェクト用にそれを変更することはできませんでした。
samiup 2017年

4
問題は、なぜWebApiシリアライザがデフォルトで「__BackingField:」を追加するのかということです。
Teoman Shipahi 2017年

良い解決策。私の場合、[Serializable] save to memcacheを使用する必要があります。シリアライズ可能が必要です。
ビングエン・クアン

2
StackOverflowなしで何ができますか?ありがとう。
camainc 2018

35

[Serializable]従来のメソッドを使用してシリアル化できるようにマークされているオブジェクトがいくつかありますが、Web APIで使用するにはJSONで完全にシリアル化する必要があります。に設定IgnoreSerializableAttributeするtrueと、Newtonsoft.JsonがMicrosoftのシリアライザーのように動作しなくなり、代わりにパブリックプロパティがシリアル化されます。

TLDR:これをWebApiConfig.csに追加します。

((Newtonsoft.Json.Serialization.DefaultContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver).IgnoreSerializableAttribute = true;

モデレーター:何度も尋ねられた質問に対する本当に良い答えを削除するのではなく、重複する質問を削除してください。これは有効な質問に対する有効な回答です。


3
これは正解です。シリアライゼーションを削除したり、datacontractおよびdatamember属性を使用したりすることは、常に正しい解決策とは限りません。
Houssam Hamdan 2017

私たちの多くは、OPを含め、WebapiやMVVMを使用していません。service.svcを使用して通常のSOAP WCFサービスがある場合のapp_startおよびwebapiconfigとは何ですか?
クリスチャン

10

データ公開するためのシンプルで適切な方法オブジェクト内のデータを、読みやすく一貫した形式で簡単に公開する必要があります。


最初に[Serializable]を削除します

    [Serializable]

ここで、クラスに[DataContract]を追加し、以下の例のようなプロパティに[DataMember]を追加します

[DataContract]
public class UserDiscretion : UserReport
{
    [DataMember]
    public String DiscretionCode { get; set; }
    public String DiscretionDescription { get; set; }
}

このヘルプホープ
感謝を。


1
Web APIを使用している場合、DataContract属性とDataMember属性を追加する必要はありません。オブジェクトを返すだけで、自動的にシリアル化されます。
Jon Story

ゼロから開発を始める人がいる場合、オブジェクトの戻り値の型を提供するWeb APIを使用すると、クライアントに公開するために型キャストを行う必要がなくなります。しかし、@ AlumCloud.comの質問の場合、彼が既存のアプリケーションにいる場合、問題の解決策はまず[Serializable]を削除し、次に[DataContract]をクラスに追加し、[DataMember]を以下のようなプロパティに追加します
Nagendra Upwanshi

1
これは、クラスに膨大な量の「ノイズ」を追加し、本質的に不要です(他のすべてのコメントを参照)。ただし、実際にこれを行う必要があると感じた場合は、PostSharpなどを使用して、コンパイル時にコードを追加し、クラスがこれらの属性でいっぱいにならないようにすることをお勧めします。
camainc

7

いくつかのオプション:

  1. [Serializable]モデルから削除

  2. 追加[DataContract][DataMember]一緒にあなたのモデルに [Serializable]

  3. 以下の行を追加 App_Start/WebApiConfig.cs

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();

3

JSON.NETの場合に役立つ別のソリューション。[Newtonsoft.Json.JsonObject]属性でクラスをマークすることで十分かもしれません。

私はxsdから構築されたcsクラスを使用していて、部分クラスを使用していくつかのプロパティを追加していました。JSONシリアル化の後、これらのプロパティはk_BackingFieldでマークされました。他の回答で言及されているJsonFormatter設定も役に立ちましたが、より単純なのは[JsonObject]属性で部分クラスをマークすることでした。


2

属性DataContractJsonSerializerを持つ別のアセンブリのクラスで使用していましたSerializable。出力には「k__BackingField」が含まれていました。Serializable(他のアセンブリの)属性を削除すると、これが修正されました。なぜだかわかりません。


0

MVCプロジェクト内でこの問題が発生していると想定すると、@ Html.JsonDataの使用を置き換えるのは非常に簡単です。これは、過去に私のために働いたコードのスニペットです:

<input type="hidden" id="Model" value="@Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model))" />

エレガントではありませんが、ピンチではシンプルです。


0

次のようなクラスに自己参照プロパティがあると、この問題が発生しました。

class Person {
 List<Person> Friends { get; set;}
}

そして結果があり、その人は自分と友達でした。結果セットに自己参照オブジェクトがないことを確認しました。お役に立てれば。



0

私の場合、このエラーはNewtonsoft.Jsonバージョンに関するもので、サーバーは6.0.0バージョンを探していて、11.0があったため、バージョン6.0.0をインストールする必要がありました。


-2

友達、このようなプロパティを宣言しないでください:

public String DiscretionCode { get; set; }
public String DiscretionDescription { get; set; }

ただし、古いように補助変数を作成します。

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}

1
どうして?思い返していただけませんか?
Lucenty 2017

@Lucentyは、このようなJSONを提供します。[{"discreationCode": "x"}]、シリアライズするとき。
Ammar Ameerdeen 2017

しかし、これは私が期待することです-これはJSONがデータをシリアル化する方法です。そして、補助変数を使用したコードでも同じ結果が得られると思います。
Lucenty 2017

k_BackingFieldが追加され、自動プロパティがシリアル化されたことを示します。自動プロパティをプロパティとバッキングフィールドにリファクタリングすると、問題はなくなります。このスレッドにはもっと良い解決策があると思いますが、これはうまくいきます。
timB33 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.