3

SO にはおそらく 500 のこのような質問があり、100 万の Web サイトがすべてちょっとした情報を提供していますが、木に木が見えません。これは恥ずかしいほど簡単なように思えますが、私はそれを機能させることができません。

シリアル化された JSON オブジェクトを返す WCF Web サービスがあります。

[OperationContract(Name = "PeopleData"), WebGet(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "people/{subset}", ResponseFormat = WebMessageFormat.Json)]
PeopleObject GetPeople(string subset);

これは機能します - ブラウザーからその URI にアクセスすると、GetPeople が呼び出され、JSON でシリアル化された値が返されますPeopleObject(プライバシーのために実際のデータ値は編集されています)。

{"HashValue":"XXXXX","People":[{"EmailAddress":"XXXXX","EmployeeID":99999,"Gender":"X","JobTitle":"XXXXX","Office":"","PreferredName":"XXXXX","Surname":"XXXXX","WorkExtensionNumber":"XXXXX","WorkPhoneNumber":"XXXXX","Department":"XXXXX","DeskNumber":"XXXXX","EmploymentClassification":"XXXXX","InternationalExtensionNumber":"XXXXX","IsFirstAider":false,"Languages":[{"LanguageID":9,"LanguageSkillID":9},{"LanguageID":9,"LanguageSkillID":9}],"QualificationInitials":"XXXXX","QualificationTitle":"XXXXX","Secretaries":null,"WorkMobilePhoneNumber":"XXXXX"}],"RecordCount":"1","SizeBytes":"12345"}

この例では、PeopleObjectペイロードにPersonはコレクション内のオブジェクトが 1 つだけ含まれていますが、多くのオブジェクトを含めることができます ( /{subset}.

これは、ペイロードに関するいくつかのメタデータと、オブジェクトPeopleObjectの List<> を保持する最上位のコンテナです。Personこれらのオブジェクトには一連の単純な型属性があり、さらに 2 つの入れ子になったLanguageandSecretaryオブジェクトの List<> があります (データが入力されている場合とされていない場合があります)。

  [DataContract]
  public class PeopleObject
  {
    [DataMember]
    public string HashValue { get; set; }
    [DataMember]
    public List<Person> People { get; set; }
    [DataMember]
    public string RecordCount { get; set; }
    [DataMember]
    public string SizeBytes { get; set; }
  }

  [DataContract]
  public class Person
  {
    [DataMember]
    public string EmailAddress { get; set; }
    // <-- snip - lots of fields like this, no point listing them all here
    [DataMember]
    public bool IsFirstAider { get; set; }
    [DataMember]
    public List<Language> Languages { get; set; }
    [DataMember]
    public List<Secretary> Secretaries { get; set; }
  }

  [DataContract]
  public class Language
  {
    [DataMember]
    public int LanguageID { get; set; }
    [DataMember]
    public int LanguageSkillID { get; set; }
  }

  [DataContract]
  public class Secretary
  {
    [DataMember]
    public int EmployeeID { get; set; }
    [DataMember]
    public char FirstSurnameLetter { get; set; }
  }

これまでのところ、WCF はすべてのフィールドとその内容を含む JSON 構造で応答します。次に、クライアント アプリケーションでその構造を逆シリアル化します (同じクラス階層定義を使用)。

  // I have a little helper-class to manage the WCF request and return a Stream
  using (Stream response = wcfHelper.GetRequestResponseStream(MY_WCF_URI))
  {
    // This is debug code to prove the response arrives as expected - it does
    //StreamReader sr = new StreamReader(response);
    //Console.WriteLine("\nResponse:\n{0}", sr.ReadToEnd());

    // Deserialise the response
    DataContractJsonSerializer dc = new DataContractJsonSerializer(typeof(PeopleObject));
    PeopleObject p = (PeopleObject)dc.ReadObject(response);

    // The object shows 1 record (in the example) but nothing in the List<>
    Console.WriteLine("\nDeserialized records: '{0}' [{1}]", p.RecordCount, p.People.Count);
  }

これにより、コンテナー オブジェクトが正しく逆シリアル化され、レコード数、ハッシュ値、およびペイロード サイズ (バイト単位) が得られます。オブジェクトには Person オブジェクトの List<> もありますが、null です。JSON 応答のコンテンツは、Person オブジェクトを作成して追加することによって List<> を正常に復元していません。

私は何が欠けていますか?私の理解では、JSON 構造からの C# オブジェクト階層のこの再水和は自動的に行われるべきであるということでした。そのため、そうではない (そして、それを実現するために何らかのコードを記述する必要があります) か、そうなっていますが、何か明らかなことを見逃していました。

4

1 に答える 1