[英]JSON Deserialization Despair (unable to deserialize nested types)
There are probably 500 questions like this on SO, and a million websites out there all offering tidbits of information - but I just can't see the wood for the trees. 在SO上可能有500个这样的问题,并且有一百万个网站都提供了一些信息 - 但我根本看不到木头的树木。 This seems like it should be embarrassingly simple to do, but I just can't make it work.
这看起来应该是令人尴尬的简单,但我无法让它工作。
I have a WCF webservice that returns a serialized JSON object: 我有一个返回序列化JSON对象的WCF Web服务:
[OperationContract(Name = "PeopleData"), WebGet(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "people/{subset}", ResponseFormat = WebMessageFormat.Json)]
PeopleObject GetPeople(string subset);
This works - if I hit that URI from a browser, GetPeople is invoked and returns a JSON-serialized PeopleObject
(actual data values redacted for privacy here): 这是有效的 - 如果我从浏览器中获取该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"}
In this example the PeopleObject
payload contains just one Person
object in the collection, but could contain many (depending on the parameter supplied in /{subset}
. 在此示例中,
PeopleObject
有效内容在集合中仅包含一个Person
对象,但可以包含多个(取决于/{subset}
提供的参数/{subset}
。
Here is the class hierarchy for PeopleObject
- it's a top-level container holding some metadata about the payload, and a List<> of Person
objects. 这是
PeopleObject
的类层次结构 - 它是一个顶级容器,包含有关有效负载的一些元数据,以及一个List <>的Person
对象。 Those objects in turn have a bunch of simple type attributes, plus two further nested List<> of Language
and Secretary
objects (which may or may not be populated): 这些对象又有一堆简单的类型属性,另外还有两个嵌套的List <>
Language
和Secretary
对象(可能填充也可能不填充):
[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; }
}
So far, so good - WCF responds with a JSON structure that contains all the fields and their contents. 到目前为止,非常好--WCF以包含所有字段及其内容的JSON结构进行响应。 Now to deserialize that structure in a client application (using the same class hierarchy definitions):
现在,在客户端应用程序中反序列化该结构(使用相同的类层次结构定义):
// 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);
}
So this correctly deserializes the container object, giving me the record count, hash value, and payload size in bytes. 所以这正确地反序列化容器对象,给我记录计数,哈希值和有效负载大小(以字节为单位)。 The object does also have a List<> of Person objects, but it's null - the content from the JSON response hasn't successfully rehydrated the List<> by creating and adding a Person object.
该对象还有一个List <> of Person对象,但它是null - 来自JSON响应的内容未通过创建和添加Person对象成功地重新水化List <>。
What am I missing? 我错过了什么? My understanding was that this rehydration of the C# object hierarchy from the JSON structure should happen automatically, so either that's not the case (and I need to write some code to make it happen) or it is, but I've missed something obvious.
我的理解是,从JSON结构中对C#对象层次结构的这种补充应该自动发生,所以要么不是这种情况(我需要编写一些代码来实现它),或者它是,但我错过了一些明显的东西。
I haven't done what you are doing before, but judging by the documentation , I'd assume the following would work: 我之前没有做过你正在做的事情,但从文档判断,我认为以下内容可行:
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);
You basically need to tell the Serializer all the types it may encounter while serializing/deserializing your object. 在序列化/反序列化对象时,您基本上需要告诉Serializer它可能遇到的所有类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.