web-dev-qa-db-ja.com

JSONのC#自動プロパティデシリアライゼーション

JSONで表されるJavaScriptオブジェクトを適切なC#クラスにデシリアライズする必要があります。自動プロパティのニース機能を考えると、フィールドを単に持つのではなく、これらのクラスにそれらを持たせることを好みます。残念ながら、.NETシリアル化エンジンは(少なくとも既定では)デシリアル化の自動プロパティを完全に無視し、バッキングフィールドのみを考慮します。バッキングフィールドはJavaScriptオブジェクトには存在しません。

バッキングフィールドに名前を付ける標準的な方法がない があることを考えると、正直なところ、「C#バッキングフィールドがあるように見えるJavaScriptオブジェクトを作成しましょう」というアプローチに煩わされたくはありません。少し汚い、シリアル化エンジンに何らかの方法でバッキングフィールドを無視させ、プロパティを直接使用することができる場合、JavaScriptフィールドをC#自動プロパティにシリアル化できる唯一の方法です。残念ながら、私はこれがどのように行われるのか、またはこれがまったく行われるのかを理解できません。どんなアイデアでも大歓迎です。

[〜#〜] edit [〜#〜]:次に例を示します。

Javascript:

function Cat()
{
    this.Name = "Whiskers";
    this.Breed = "Tabby";
}
var cat = new Cat();

これは、「{Name: 'Whiskers'}」にシリアル化されます。

C#クラス:

[Serializable()]
public class Cat
{
    public string Name { get; set; }
    public string Breed { get; set; }
}

そして、失敗する逆シリアル化コード:

new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream);

また、例外から、バッキングフィールドを探しているために失敗することが明らかです。

EDIT2:これが役立つ場合の例外を次に示します(内部例外はありません):

System.Runtime.Serialization.SerializationException

「データコントラクトタイプ「Test.Cat」は、必要なデータメンバー「<Name>k__BackingField, <Breed>k__BackingField 'が見つかりませんでした。」

50
Tamas Czinege

ここで起こっているのは、デシリアライザがバッキングフィールドの名前を推測しようとしていることです。これを解決するには、次のような明示的なマッピング(DataContract/DataMember属性)を追加します。

[DataContract]
public class Cat
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string Breed { get; set; }
}
80
baretta

System.Web.Script.Serialization名前空間にあるJavaScriptSerializerを使用してこれを行うことができます。

JavaScriptSerializer serializer = new JavaScriptSerializer();
Cat c = serializer.Deserialize<Cat>(jsonString);

自動プロパティを持つPOCOオブジェクトがあり、これは問題なく機能します。

編集: 。NETのJSONシリアライザー について書きました。このシリアライザーをDataContractJsonSerializerと比較します。

20
aleemb

バレッタの答え k__BackingFieldの膨張を解決してくれました。同様の方法でXMLまたはJSONに自動シリアル化するために、このクラスを装飾することができるほんの小さな補足事項:

[Serializable, XmlRoot, DataContract]
public class Cat
{
  [XmlElement]
  [DataMember]
  public string Name { get; set; }
  [XmlElement]
  [DataMember]
  public string Breed { get; set; }
}

...次に、DataContractJsonSerializerまたはXmlSerializerを使用して、エンドポイント用に準備します。

5
amelvin

Webサービスを介してデータを渡すと仮定しています。 ScriptMethod属性をコメントアウトせずにWebServiceクラスを使用している場合、WebサービスメソッドはJSONをネイティブに読み取ることができます。上記で説明したのと同じJavaScriptSerializerも使用します。 WCFを使用している場合は、ロジックが少し曖昧です。

ただし、JSONオブジェクトがクラスのすべてのプロパティのデータを返していることを確認してください。あなたのエラーには、あなたの例にはない品種プロパティの言及があります。

また、JavaScript側では、JavaScriptの動的な性質を利用して、オブジェクトに新しいプロパティを簡単に追加できます。これにより、循環参照が発生する場合があります。追加した可能性のある余分なデータはすべて削除する必要があります(Webメソッドを介してデータを送信するときと同様に、完了したら再度追加します)。

1
Chris Brandsma