JSON反序列化绝望(无法反序列化嵌套类型)

时间:2013-06-20 12:50:53

标签: c# json deserialization

在SO上可能有500个这样的问题,而且有一百万个网站都提供了一些信息 - 但我根本看不到木头的树木。这看起来应该是令人尴尬的简单,但我无法使其发挥作用。

我有一个返回序列化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对象,但可以包含多个(取决于/{subset}中提供的参数。

以下是PeopleObject的类层次结构 - 它是一个顶层容器,包含有关有效负载的一些元数据,以及List<> Person个对象。这些对象又有一堆简单的类型属性,另外还有两个嵌套的List<> LanguageSecretary个对象(可能填充也可能不填充):

  [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);
  }

所以这正确地反序列化容器对象,给我记录计数,哈希值和有效负载大小(以字节为单位)。该对象还具有List&lt;&gt; Person对象,但它是null - 来自JSON响应的内容未成功重新水化List&lt;&gt;通过创建和添加Person对象。

我错过了什么?我的理解是,从JSON结构中对C#对象层次结构的这种补充应该自动发生,所以要么不是这种情况(我需要编写一些代码来实现它),或者它是,但我错过了一些明显的东西。

1 个答案:

答案 0 :(得分:1)

我之前没有做过你正在做的事情,但是根据documentation来判断,我认为以下方法可行:

List<Type> types = new List<Type>();
types.Add(typeof(Person));
types.Add(typeof(Language));
types.Add(typeof(Secretary));

DataContractJsonSerializer dc = new DataContractJsonSerializer(typeof(PeopleObject), types);
PeopleObject p = (PeopleObject)dc.ReadObject(response);

在序列化/反序列化对象时,您基本上需要告诉Serializer它可能遇到的所有类型。