I have some data which I need to bring from an XML file to a PostgreSQL database through a C# application I am currently working on.
The problem I face now is that I need to add some kind of list to the XML now. Currently it looks something like this:
<itemOne>stuff</itemOne>
<itemTwo>otherStuff</itemTwo>
<listOfItems>
<listItem>
<partOne>123</partOne>
<partTwo>abc</partTwo>
</listItem>
<listItem>
<partOne>123</partOne>
<partTwo>abc</partTwo>
</listItem>
</listOfItems>
So I found quite some threads which handle the topic of how to deserialize lists. But all of them start by saying that the proposed XML should be modified. As I have all the freedom that I could wish for in that regard, I'd like to first create an optimal XML format at first.
Well, and afterwards deserialize it. So if there is any format for lists which is automatically processed by XmlSerializer.Deserialize() it would be amazing.
That data will already be processed automatically by XmlSerializer, as long as the class is shaped to match. For example:
[XmlRoot("yourRootName")]
public class Foo {
[XmlElement("itemOne")] public string A {get;set;}
[XmlElement("itemTwo")] public string B {get;set;}
[XmlArray("listOfItems")]
[XmlArrayItem("listItem")]
public List<Bar> Bars {get;set;}
}
public class Bar {
[XmlElement("partOne")] public int C {get;set;}
[XmlElement("partTwo")] public string D {get;set;}
}
Of course, if it was me I'd be tempted to be terse, with:
<betterName foo="stuff" blab="otherStuff">
<nameMe a="123" b="abc"/>
<nameMe a="456" b="def"/>
</betterName>
which just requires some minimal changes:
[XmlRoot("betterName")]
public class Foo {
[XmlAttribute("foo")] public string A {get;set;}
[XmlAttribute("bar")] public string B {get;set;}
[XmlElement("nameMe")]
public List<Bar> Bars {get;set;}
}
public class Bar {
[XmlAttribute("a")] public int C {get;set;}
[XmlAttribute("b")] public string D {get;set;}
}
Related
Currently, I have some JSON data that I am attempting to deserialize using the DataContractJsonSerializer class. However, one of the arrays in the data contains multiple types of objects. Is there a way to deserialize this data properly? I am aware that a very similar question exists, but I would prefer not to use Json.NET or any other third-party libraries.
EDIT: A small example:
In this instance, let's say the JSON is of form [{"foo":string},{"bar":string},{"foo":string},{"foo":string},...] where each element is either of form {"foo":string} or {"bar":string}. Then, the contracts could be set up as such:
[DataContract]
class Foo { [DataMember] public string foo; }
[DataContract]
class Bar { [DataMember] public string bar; }
In this context, my question is, how do I deserialize this array of Foos and Bars?
This does not sound right. There should not be two completely different types in a single array. Given the JSON provided I would try something like this....
[DataContract]
class SomeClass
{
[DataMember]
public string foo { get; set;}
[DataMember]
public string bar { get; set;}
}
Then check for IsNullOrWhiteSpace() on each property.
Updated with more code...
static void Main(string[] args)
{
SomeClass[] output;
var json = "[{\"foo\":\"value\"},{\"bar\":\"value\"},{\"foo\":\"value1\"},{\"foo\":\"value1\"}]";
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
var deserializer = new DataContractJsonSerializer(typeof(SomeClass[]));
output = (SomeClass[])deserializer.ReadObject(ms);
}
// do something with output
Console.WriteLine(output.Length);
}
I'm using RestSharp and trying to deserialise a collection of nodes into a property in a class:
client.Execute<Foo>(req);
where
public class Foo
{
public List<Bar> Bar{get;set;}
...
}
public class Bar
{
public int Id{get;set;}
public string Name{get;set;}
}
and the xml response is:
<Foo>
<Bar><Id>4</Id><Name>asdf4</Name></Bar>
<Bar><Id>5</Id><Name>asdf5</Name></Bar>
<Bar><Id>6</Id><Name>asdf6</Name></Bar>
</Foo>
But, always the property has one Bar element with all fields set to null. I've researched and all the answers suggested using as few classes as necessary. Here that isn't possible. What do I have to do to get this response formatted into a list? I've also tried specifying the xml deserializer explicitly to the DotNet deserializer as per a question from a few years ago to no joy.
To get the List<Bar> that you want, you just need to change your Execute<T> to:
client.Execute<List<Bar>>(req);
Edit
Based on your comment, Foo has other properties. So your class may look something like this:
public class Foo
{
public List<Bar> Bar {get;set;}
public string OtherProperty { get; set; }
}
I think you may need to change your xml, if at all possible, to be more like this:
<Foo>
<Bars>
<Bar><Id>4</Id><Name>asdf4</Name></Bar>
<Bar><Id>5</Id><Name>asdf5</Name></Bar>
<Bar><Id>6</Id><Name>asdf6</Name></Bar>
</Bars>
<OtherProp>this</OtherProp>
</Foo>
And then change your Foo to:
public List<Bar> Bars {get;set;}
If you are able to alter your xml structure, and change that class, your client.Execute<Foo>(req); should give you what you want.
I need to serialize some XML to an object. I don't have control over the structure of the XML so I'm stuck with this situation. The structure is similar to this example:
<A>
<B>Elements that are the stuff of B</B>
<C>Stuff about the stuff in B</C>
<B>Different stuff</B>
<C>Stuff about the different stuff</C>
<C>Some more stuff about the different stuff</C>
<B>Weird stuff</B>
<C>Stuff about the Weird Stuff</C>
<C>Still more stuff about the Weird Stuff</C>
<D>New thing that goes with the Weird Stuff</D>
<B>Things</B>
<C>Stuff about Things</C>
</A>
I'd like to get this serialized to an object that maintains the information about the sibling structure.
public class A
{
public List<BCD> BCD {get; set;}
}
public class BCD
{
public B Bfield {get; set;}
public List<C> Cfield {get; set;}
public D Dfield {get; set;}
}
public class B
{
// class details
}
public class C
{
// class details
}
public class D
{
// class details
}
When I try this, it doesn't work. Is there anything I can do to maintain that structure using the XMLSerializer?
So I kept looking around for a solution and came up with this which is not exactly what I was looking for. This class structure retains the order of the sibling elements within the collection but does not create objects to represent a discrete group of the siblings.
public class A
{
[XmlElementAttribute("B", typeof(B))]
[XmlElementAttribute("C", typeof(C))]
[XmlElementAttribute("D", typeof(D))]
public List<object> BCD {get; set;}
}
public class B
{
// class details
}
public class C
{
// class details
}
public class D
{
// class details
}
The end result is BCD is a collection of the B,C,D objects in the order they appear in the XML.
You can try below steps:
convert your xml to xslt using xsd.exe(feature of VS)
convert xslt to class again by using xsd.exe
try to serialize and deserialize your xml to this class object.
now you can play with this class object to perform any action.
Hope this will help..
I have a parent class that I want to have many flat children. That means 10 or more different classes would inherent from one class.
Here is what I have.
Base Class:
[ProtoContract]
[ProtoInclude(500, typeof(Message1Send))]
[ProtoInclude(501, typeof(Message2Send))]
public class MessageBase
{
[ProtoMember(1)]
public string Topic {get;set;}
[ProtoMember(2)]
public string Action { get; set; }
}
2 of many Child Classes:
[ProtoContract]
public class Message1Send : MessageBase
{
[ProtoMember(1)]
public string Property1 { get; set; }
}
[ProtoContract]
public class Message2Send : MessageBase
{
[ProtoMember(1)]
public string Property1 { get; set; }
}
I want to be able to tell the child object I am part of a base class.
I don’t what to get to the point where my base class is as follows:
[ProtoContract]
[ProtoInclude(500, typeof(Message1Send))]
[ProtoInclude(501, typeof(Message2Send))]
[ProtoInclude(502, typeof(Message3Send))]
[ProtoInclude(503, typeof(Message4Send))]
[ProtoInclude(504, typeof(Message5Send))]
[ProtoInclude(505, typeof(Message6Send))]
[ProtoInclude(506, typeof(Message7Send))]
[ProtoInclude(507, typeof(Message8Send))]
[ProtoInclude(508, typeof(Message9Send))]
[ProtoInclude(509, typeof(Message10Send))]
public class MessageBase
{
[ProtoMember(1)]
public string Topic {get;set;}
[ProtoMember(2)]
public string Action { get; set; }
}
Is there a way I can have each one of the Send classes to just add one reference to the base class so I don’t have to keep adding ProtoInclude for every flat child I create?
The problem is one of reliability. Reflection makes veryfew repeatable / reliable guarantees, and it is very important that if you serialize data today, then edit your app to add two new types, each type still has the same number as it did oroginally. Even if you've added some new types, renamed some, and possibly removed two that you weren't really using.
The attribute guarantees this by making the field-number repeatable. The reason it is on the parent (not the child) is that it is much more reliable to walk up the type-chain than down it.
However: if you have a reliable repeatable way of generating field numbers for sub-types, you can use RuntimeTypeModel to configure the serializer to your liking.
I have 4 tables in the DB, each one has Id and Name, but they represent different things.
for each "thing" i have a different class, they all inherit from "thing".
i have 4 functions :
List<thing1> getAllThings1();
List<thing2> getAllThings2();
List<thing3> getAllThings3();
List<thing4> getAllThings4();
each function reads from different table and creates the needed list.
Because i want to avoid code duplication i wanted to make a utility function that receives the table name (as string) and the type (thing1, thing2 ... etc), and returns List<t>.
unfortunately this is impossible (without reflection) :
Create list of variable type
My current solution is that i have a function that returns a List, i call her in each "getAllThings#" and then manually convert each "thing" in the list to the proper thing by using ConvertAll and passing to him some converter.
I don't like this solution, it feels wrong because i create a list and create a new one. very inefficient.
is there a better way to do it ?
thanks
Why not use generics?
public IList<T> GetAllThings<T>(string tableName) where T : Thing {
return new List<T>();
}
You will be able to call it
IList<Thing4> things4 = thingProvider.GetAllThing<Thing4>( "thing4Table" );
you could also have a Dictionary for storing the table name for each type, so you don't have to provide the table name to the method.
try this quick and dirty. Not actual ,might contains error, you can use it as a reference.
Create a base class of thing having all common attributes
abstract ThingBase
{
protected abstract int Id {get;set;}
protected abstract string Name {get;set;}
}
Implement that base to your four things classes
public Thing1 :ThingBase
{
public int Id {get;set;}
public string Name {get;set;}
}
public Thing2 :ThingBase
{
public int Id {get;set;}
public string Name {get;set;}
}
public Thing3 :ThingBase
{
public int Id {get;set;}
public string Name {get;set;}
}
public Thing4 :ThingBase
{
public int Id {get;set;}
public string Name {get;set;}
}
Create one more helper class, that will contain the list of all 4 things
public class YourThings
{
public IList<Thing1> thing1 {get;set;}
public IList<Thing2> thing2 {get;set;}
public IList<Thing3> thing3 {get;set;}
public IList<Thing4> thing4 {get;set;}
}
Now Write 4 different Select Queries in your SP and catch it as a dataset in your datalayer. Extract the table and fill its respective list and return yourthing class to the UI layer.
public YourThings FunctionToReturnSingleYourThing()
{
}
of If You need a collection of YourThings , rebuild your logic and return like this
public List<YourThings> FunctionToReturnMultipleYourThings()
{
}