DataContract Serialization of List<> containing objects
While developing a test case to understand serialization, I've run into what looks like a straighforward problem but am unable to figure out. I want to be able to add multiple objects to a list<> and then serialize that list (in this case I'm using DataContractJsonSerializer). After creating the objects (node1 and node2), I want to add them to a List<> (cn) and serialize it. However, I get an invalid argument error when adding node1 and node2 ("cannot convert from 'JSON_test.Aspirate' to 'JSON_test.CompositeNode'). I believe it is a matter of letting the array know about the base types, but I don't know how to do that, or if in fact that is the issue (still very new to all this).
Thank you.
namespace JSON_test
{
class Program
{
开发者_运维知识库 static void Main(string[] args)
{
Aspirate node1 = new Aspirate(25,40);
Dispense node2 = new Dispense(32,50);
ObjectToSerialize cn = new ObjectToSerialize();
cn.CompositeNode.Add (node1);
cn.CompositeNode.Add (node2);
MemoryStream stream1 = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ObjectToSerialize));
ser.WriteObject(stream1, cn.CompositeNode);
stream1.Position = 0;
StreamReader sr = new StreamReader(stream1);
Console.WriteLine(sr.ReadToEnd());
Console.ReadLine();
}
}
[DataContract]
public class ObjectToSerialize
{
private List<CompositeNode> compNode;
[DataMember]
public List<CompositeNode> CompositeNode
{
get {return this.CompositeNode;}
set { this.compNode = value; }
}
public ObjectToSerialize()
{
}
}
[DataContract]
public class CompositeNode
{
}
[DataContract]
public class Aspirate
{
[DataMember]
public string NodeName = "Aspirate";
[DataMember]
public double ZTravelHt;
[DataMember]
public double IndexHt;
public Aspirate(double ZTravelHt, double IndexHt)
{
this.ZTravelHt = ZTravelHt;
this.IndexHt = IndexHt;
}
}
[DataContract]
public class Dispense
{
[DataMember]
public string NodeName = "Dispense";
[DataMember]
public double ZTravelHt;
[DataMember]
public double IndexHt;
public Dispense(double ZTravelHt, double IndexHt)
{
this.ZTravelHt = ZTravelHt;
this.IndexHt = IndexHt;
}
}
}
UPDATE
namespace JSON_test
{
class Program
{
static void Main(string[] args)
{
Aspirate node1 = new Aspirate(25,40);
Dispense node2 = new Dispense(32,50);
ObjectToSerialize cn = new ObjectToSerialize();
cn.CompositeNode.Add (node1);
cn.CompositeNode.Add (node2);
MemoryStream stream1 = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ObjectToSerialize),
new Type[] {typeof (Aspirate), typeof (Dispense)});
ser.WriteObject(stream1, cn.CompositeNode);
stream1.Position = 0;
StreamReader sr = new StreamReader(stream1);
Console.WriteLine(sr.ReadToEnd());
Console.ReadLine();
}
}
[DataContract]
[KnownType(typeof(Aspirate))]
[KnownType(typeof(Dispense))]
public class ObjectToSerialize
{
private List<CompositeNode> compNode = new List<CompositeNode>();
[DataMember]
public List<CompositeNode> CompositeNode
{
get {return this.compNode;}
set { this.compNode = value; }
}
public ObjectToSerialize()
{
}
}
[DataContract]
[KnownType(typeof(Aspirate))]
[KnownType(typeof(Dispense))]
public class CompositeNode
{
}
[DataContract]
public class Aspirate : CompositeNode
{
[DataMember]
public string NodeName = "Aspirate";
[DataMember]
public double ZTravelHt;
[DataMember]
public double IndexHt;
public Aspirate(double ZTravelHt, double IndexHt)
{
this.ZTravelHt = ZTravelHt;
this.IndexHt = IndexHt;
}
}
[DataContract]
public class Dispense : CompositeNode
{
[DataMember]
public string NodeName = "Dispense";
[DataMember]
public double ZTravelHt;
[DataMember]
public double IndexHt;
public Dispense(double ZTravelHt, double IndexHt)
{
this.ZTravelHt = ZTravelHt;
this.IndexHt = IndexHt;
}
}
}
You can add a KnownTypeAttribute
to the ObjectToSerialize
to let the serializer know which types to expect:
[DataContract]
[KnownType(typeof(Aspirate))]
[KnownType(typeof(Dispense))]
public class ObjectToSerialize
{
....
}
I understand that the classes Aspirate
and Dispense
are derived from CompositeNode
? This is not clear from your code example.
You have an error in your code by the way:
get {return this.CompositeNode;}
should be:
get {return this.compNode;}
Update: in resoponse to your question in the comments: you have to intialize the collection inside a constructor of ObjectToSerialize:
public ObjectToSerialize()
{
this.compNode = new List<CompositeNode>();
}
Update 2: The line that is wrong is:
ser.WriteObject(stream1, cn.CompositeNode);
This should be:
ser.WriteObject(stream1, cn);
By the way, you can just write this:
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ObjectToSerialize));
You already defined the known types by using attributes. Adding the known types to the constructor is redundant.
精彩评论