简体   繁体   中英

DataContractSerializer does not deserialize collection of objects

Good evening, I have the following XML:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<project xmlns="">
  <title>MyProject</title>

  <nodes>
    <node>
      <name>base</name>
      <class>BaseNode</class>
    </node>

    <node>
      <name>detail</name>
      <class>DetailNode</class>
    </node>
    ...
  </nodes>
</project>

... that I'd wish to deserialize into the following object structure, so that a Project contains a "Title" and a NodeCollection (which in turn contains multiple Node elements):

[DataContract(Name = "project")]
class Project
{
    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "nodes")]
    public NodeCollection Nodes { get; set; }
}

[CollectionDataContract(Name = "nodes", ItemName = "node")]
class NodeCollection : List<Node>
{

}

[DataContract(Name = "node")]
class Node
{
    [DataMember(Name = "name")]
    public string Name { get; set; }

    [DataMember(Name = "class")]
    public string Class { get; set; }
}

With this architecture, deserialization completes without errors, returning an expected Project object, but:

  • Project "Title" is deserialized correctly (its value being "MyProject"),
  • Project "Nodes" is not (empty).

The Title property on the Project object is set to the expected value, but the NodeCollection is always empty. In fact, it's not even initialized:

Object reference not set to an instance of an object

For some odd reason, the deserializer "does not recognize any nodes". I tried adding the KnownType attribute, no success.

What am I doing wrong?

It works if you specify the Namespace and Order attributes; otherwise it complains about unexpected namespaces or fails to read the node(s) entirely, and for some reason it's expecting Title to come after Nodes .

[DataContract(Name = "project", Namespace="")]
public class Project
{
    [DataMember(Name = "title",Order=1)]
    public string Title { get; set; }

    [DataMember(Name = "nodes", Order=2)]
    public NodeCollection Nodes { get; set; }
}

[CollectionDataContract(Name = "nodes",Namespace="", ItemName = "node")]
public class NodeCollection : List<Node> {  }

[DataContract(Name = "node", Namespace="")]
public class Node
{
    [DataMember(Name = "name")]
    public string Name { get; set; }

    [DataMember(Name = "class")]
    public string Class { get; set; }
}

Looking at the documentation ,

The basic rules for data ordering include:

  • If a data contract type is a part of an inheritance hierarchy, data members of its base types are always first in the order.
  • Next in order are the current type's data members that do not have the Order property of the DataMemberAttribute attribute set, in alphabetical order.
  • Next are any data members that have the Order property of the DataMemberAttribute attribute set. These are ordered by the value of the Order property first and then alphabetically if there is more than one member of a certain Order value. Order values may be skipped.

Because "N" comes before "T" alphabetically, it was expecting NodeCollection to be first. Even though things are "out of order", it will still deserialize (which seems strange, but that's how it works) - it just will fill those objects/members with null.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM