Question about XML deserialization in .net - c#

I'm trying to deserialize an XML that comes from a web service but I do not know how to tell the serializer how to handlke this piece of xml:
<Movimientos>
<Movimientos>
<NOM_ASOC>pI22E7P30KWB9KeUnI+JlMRBr7biS0JOJKo1JLJCy2ucI7n3MTFWkY5DhHyoPrWs</NOM_ASOC>
<FEC1>RZq60KwjWAYPG269X4r9lRZrjbQo8eRqIOmE8qa5p/0=</FEC1>
<IDENT_CLIE>IYbofEiD+wOCJ+ujYTUxgsWJTnGfVU+jcQyhzgQralM=</IDENT_CLIE>
</Movimientos>
<Movimientos>
As you can see, the child tag uses the same tag as its parent, I suppose this is wrong however the webservice is provided by an external company and that wont change it, is there any way or any library to tidy up XML or how can I use an attribute on my class so that the serializer gets it right? thanks for any help.

The serializer should be OK with it - the issue is probably just that a class can't have a property that's the same name as the class itself. So use XmlElementAttribute to match it up:
[XmlRoot("Movimientos")]
public class Movimientos
{
[XmlElement("Movimientos")]
public SomeOtherClass SomeOtherProperty { get; set; }
}
public class SomeOtherClass
{
public string NOM_ASOC { get; set; }
public string FEC1 { get; set; }
public string IDENT_CLIE { get; set; }
}
FYI, the XML is actually not wrong; there's no rule in the spec saying that a child element can't have the same name as its parent element. It's unusual maybe, but still valid.

If this is not actually deserialized by the XML serializer of .Net, it's probably better to write your own class to parse it. You can use the System.Xml or System.Xml.Linq (easier) namespaces.

Related

C# Json Generic "Tiered" Deserialize

I'm trying to deserialize a JSON file into a generic stack of serialized objects so I can easily make a sort of tree view using a for loop.
I've done a little Googling over the past couple hours but can't seem to find anything that would allow a truly generic approach, as all seem to require using pre-declared variables, setting the max depth of the tree.
There are many online generic JSON viewers (though no code is provided) so I am sure this is possible, I just have no idea how.
The file I'm currently working with as an example is below, as is an example of how I'm trying to get this structured.
{"arcanePrefs":[{"name":"playerWalkingSpeed","category":"player","value":"6"},{"name":"playerRunningSpeed","category":"player","value":"8"},{"name":"playerLookSpeed","category":"player","value":"12"},{"name":"playerHorTurnSpeed","category":"player","value":"2"},{"name":"playerVerTurnSpeed","category":"player","value":"2"},{"name":"playerJumpHeight","category":"player","value":"6"},{"name":"playerVertLimit","category":"player","value":"80"},{"name":"playerAirCtrl","category":"player","value":"True"},{"name":"playerGravMod","category":"player","value":"1.5"},{"name":"playerHBobWlkSpd","category":"player","value":"0.18"},{"name":"playerHBobRunSpd","category":"player","value":"0.35"},{"name":"playerHBobHgt","category":"player","value":"0.4"},{"name":"playerHCant","category":"player","value":"True"},{"name":"playerReloadSpeed","category":"player","value":"1"},{"name":"playerUseRadius","category":"player","value":"0.5"},{"name":"playerWasteHealth","category":"player","value":"False"},{"name":"playerWasteArmor","category":"player","value":"False"},{"name":"playerWasteAmmo","category":"player","value":"False"},{"name":"playerHeight","category":"player","value":"1.6"},{"name":"playerBaseHealth","category":"player","value":"100"},{"name":"playerMaxHealth","category":"player","value":"250"},{"name":"playerbaseArmor","category":"player","value":"100"},{"name":"playerMaxArmor","category":"player","value":"150"},{"name":"playerWeaponSoftDrag","category":"player","value":"True"},{"name":"enemyStunLock","category":"enemy","value":"True"},{"name":"enemyGunshotDetectRaduis","category":"enemy","value":"40"},{"name":"worldWaterFallDmg","category":"world","value":"False"},{"name":"worldCanShootSwitches","category":"world","value":"True"},{"name":"worldLavaDamagePerFrame","category":"world","value":"1"},{"name":"cameraFOV","category":"camera","value":"80"},{"name":"cameraToneMapping","category":"camera","value":"True"},{"name":"cameraCustomPixel","category":"camera","value":"True"},{"name":"cameraPixelRes","category":"camera","value":"res360p"},{"name":"cameraDither","category":"camera","value":"True"},{"name":"cameraDitherStrength","category":"camera","value":"0.95"},{"name":"cameraBloom","category":"camera","value":"True"},{"name":"cameraBloomInt","category":"camera","value":"5"},{"name":"cameraUnderwaterCol1","category":"camera","value":"0.1921569;0.3921569;0.4509804;1"},{"name":"cameraUnderwaterCol2","category":"camera","value":"0.3137255;0.5882353;0.5882353;1"},{"name":"cameraUnderlavaCol1","category":"camera","value":"0.9019608;0.2313726;0;1"},{"name":"cameraUnderlavaCol2","category":"camera","value":"0.9019608;0.6666667;0.3529412;1"},{"name":"cameraCshrCol","category":"camera","value":"0.4901961;0.4901961;0.4901961;1"},{"name":"cameraCshrTgtCol","category":"camera","value":"0.7803922;0;0;1"},{"name":"arcaneLimitFPS","category":"engine","value":"True"},{"name":"arcaneFpsLimit","category":"engine","value":"-1"},{"name":"engineUIScale","category":"engine","value":"0.7"},{"name":"srcBHopping","category":"sem","value":"False"}],"arcaneControls":[{"name":"contForward","key":119},{"name":"contLeft","key":97},{"name":"contBackward","key":115},{"name":"contRight","key":100},{"name":"contRotLeft","key":113},{"name":"contRotRight","key":101},{"name":"contJump","key":32},{"name":"contLookUp","key":280},{"name":"contLookDown","key":281},{"name":"contSprintHold","key":304},{"name":"contSprintToggle","key":301},{"name":"contCrouchHold","key":306},{"name":"contCrouchToggle","key":99},{"name":"contComFire","key":323},{"name":"contComFireAlt","key":305},{"name":"contComSFire","key":324},{"name":"contComSFireAlt","key":303},{"name":"contComReload","key":114},{"name":"contComPrevWeap","key":326},{"name":"contComNextWeap","key":327},{"name":"contComInspectWeap","key":103},{"name":"contDebug","key":96}]}
What I'm trying to do
I do not use Unity, but they seem to provide newtonsoft which is a powerfull serializer / deserializer library for json link
For your use case, you want to convert json to a list of objet I think, so deserialize in this case.
To obtain an object representation of your json string you can go like
string json; // you data here
Arcane arcane=Newtonsoft.Json.JsonConvert.DeserializeObject<Arcane>(json);
public class Arcane
{
public List<ArcanePref> arcanePrefs { get; set; }
public List<ArcaneControl> arcaneControls { get; set; }
}
public class ArcanePref
{
public string name { get; set; }
public string category { get; set; }
public string value { get; set; }
}
public class ArcaneControl
{
public string name { get; set; }
public int key{ get; set; }
}
With the arcane object you can then access the acranePrefs and arcaneControls list.
To represent the json data in a tree view fashion with Unity, I found the tree view api
Which seem the most straight foward way to go for a tree view representation
Once you have your objects, it should be more or less simple.
Concerning riffnl comment, I do not have any idea what the end goal is, or what is the source you are using ^^'
Hope it helps !

Deserialize multiple XML elements have same name

i have an XML form look like this:
<Myset>
<element>1A</element>
<element>2B</element>
<element>3C</element>
<element>AB</element>
..........
<element>AA</element>
What should structure class, variables should i use to deserialize it. I want to read and update value of each element. I have try this, but it doesn't work:
public class Myset
{
public List<string> element {get; set;}
// or public string[] element { get; set; }
}
XmlElementAttribute will allow you specify element name.
public class case_id_list
{
[XmlElement("case_id")]
public List<string> case_id {get; set;}
}
You should use this service. It converts your xml structure to valid c# model structure. It's a very useful tool.
*In case you ever want to convert your JSON to C# this is another useful service.
Cheers!

How to Deserialize XML elements to generic list with unknown element names

I am retrieving and successfully deserializing an xml string from a database table column for the known element names (these do not change) but there are also some nested XML Elements called "Other Attributes" which are not always going to be known. I'm having some trouble deserialising these unknown element names to a generic list so I can display them in html once deserialised.
The XML is as follows:
<Detail>
<DetailAttributes>
<Name>Name_123</Name>
<Type>Type_123</Type>
</DetailAttributes>
<OtherAttributes>
<SummaryKey AttributeName="SummaryKey">SummaryKey_123</SummaryKey>
<Account AttributeName="Account">Account_123</Account>
</OtherAttributes>
</Detail>
I have no problem deserialising the 'Name' and 'Type' elements and I can deserialise the 'SummaryKey' and 'Account' elements but only if I explicitly specify their element names - which is not the desired approach because the 'OtherAttributes' are subject to change.
My classes are as follows:
[XmlRoot("Detail")]
public class objectDetailsList
{
[XmlElement("DetailAttributes"), Type = typeof(DetailAttribute))]
public DetailAttribute[] detailAttributes { get; set; }
[XmlElement("OtherAttributes")]
public List<OtherAttribute> otherAttributes { get; set; }
public objectDetailsList()
{
}
}
[Serializable]
public class Detail Attribute
{
[XmlElement("Type")]
public string Type { get;set; }
[XmlElement("Name")]
public string Name { get;set; }
public DetailAttribute()
{
}
}
[Serializable]
public class OtherAttribute
{
//The following will deserialise ok
//[XmlElement("SummaryKey")]
//public string sumKey { get; set; }
//[XmlElement("Account")]
//public string acc { get; set; }
//What I want to do below is create a list of all 'other attributes' without known names
[XmlArray("OtherAttributes")]
public List<Element> element { get; set; }
}
[XmlRoot("OtherAttributes")]
public class Element
{
[XmlAttribute("AttributeName")]
public string aName { get; set; }
[XmlText]
public string aValue { get; set; }
}
When I try to retrieve the deserialised list of OtherAttribute elements the count is zero so it's not able to access the elements nested within "Other Attributes".
Can anybody help me with this please?
With concrete classes and dynamic data like this, you won't be able to lean on the standard XmlSerializer to serialize / deserialize for you - as it reflects on your classes, and the properties you want to populate simply don't exist. You could provide a class with all possible properties if your set of 'OtherAttributes' is known and finite, and not subject to future change, but that would give you an ugly bloated class (and I think you've already decided this is not the solution).
Practical options therefore:
Do it manually. Use the XmlDocument class, load your data with .Load(), and iterate the nodes using .SelectNodes() using an XPath query (something like "/Detail/OtherAttributes/*"). You will have to write the lot yourself, but this gives you complete control over the serialization / deserialization. You won't have to cover your code in (arguably superfluous!) attributes either.
Use Json.NET (http://james.newtonking.com/json), it allows for far greater control over serialization and deserialization. It's fast, has good docs and is overall pretty nifty really.

how to serialize class objects to xml document

I hope to find a solution from you. What I need is to serialize ValidatorList class object into an xml document. How to do this?
I tried like this:
XmlSerializer _serializer = new XmlSerializer(list);
But I don't know how to make output of xml for list that has several classes.
C#
_list= new ListVal();
Type _type = typeof(ras);
_list.Add(new RequiredField
{
Property = _type.GetProperty("CustRef")
}.Add(new AsciiVal()));
_list.Add(new RequiredField
{
Property = _type.GetProperty("ctr")
}.Add(new StringLengthVal
{
min= 3,
max= 3
}));
[Serializable]
public class Field
{
public Field Next
{
get;
set;
}
public Field TypeName
{
get;
set;
}
public Field PropertyName
{
get;
set;
}
}
public class RequiredField : Field
{
//TODO
}
public class AsciiVal: Field
{
//TODO
}
public class StringLengthVal: Field
{
//TODO
}
public class ListVal: List<Field>
{
//TODO
}
I have something close, but not exactly the Xml you want. In actual fact I think you'll see that the Xml produced below makes a bit more sense than what you have.
To get you started, you control the serialization and deserialization using attributes in the System.Xml.Serialization namespace. A few useful ones to read up on are
XmlRootAttribute
XmlElementAttribute
XmlAttributeAttribute
XmlIncludeAttribute
So I mocked up some code which closely matches your own. Notice the addition of some attributes to instruct the serializer how I want the Xml to be laid out.
[XmlInclude(typeof(AsciiValidator))]
[XmlInclude(typeof(RequiredValidator))]
[XmlInclude(typeof(StringLengthValidator))]
public class FieldValidator
{
[XmlElement("Next")]
public FieldValidator Next
{
get;
set;
}
[XmlElement("PropertyName")]
public string PropertyName
{
get;
set;
}
}
public class AsciiValidator: FieldValidator
{
}
public class RequiredValidator: FieldValidator
{
}
public class StringLengthValidator: FieldValidator
{
[XmlElement]
public int MinLength{get;set;}
[XmlElement]
public int MaxLength{get;set;}
}
[XmlRoot("ValidatorList")]
public class ValidatorList : List<FieldValidator>
{
}
Point of interest; Every class inheriting FieldValidator must be added to the list of known types using XmlIncludeAttribute so the serializer knows what to do with them)
Then I created an example object map:
var test = new ValidatorList();
test.Add(
new RequiredValidator()
{
PropertyName="CustRef",
Next = new AsciiValidator()
});
test.Add(
new RequiredValidator()
{
PropertyName="CurrencyIndicator",
Next = new StringLengthValidator(){
MinLength=3,
MaxLength = 10
}
});
Finally I told the serializer to serialize it (and output the result to the console)
var ser = new XmlSerializer(typeof(ValidatorList));
ser.Serialize(Console.Out,test);
This was the result:
<?xml version="1.0" encoding="utf-8"?>
<ValidatorList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FieldValidator xsi:type="RequiredValidator">
<Next xsi:type="AsciiValidator" />
<PropertyName>CustRef</PropertyName>
</FieldValidator>
<FieldValidator xsi:type="RequiredValidator">
<Next xsi:type="StringLengthValidator">
<MinLength>3</MinLength>
<MaxLength>10</MaxLength>
</Next>
<PropertyName>CurrencyIndicator</PropertyName>
</FieldValidator>
</ValidatorList>
Not a million miles away from what you wanted. There is the need to output certain things in a certain way (eg xsi:type tells the serializer how to deserialize back to the object map). I hope this gives you a good start.
Here is a live, working example: http://rextester.com/OXPOB95358
Deserialization can be done by calling the Deserialize method on the XmlSerializer.
For example, if your xml is in a string:
var ser = new XmlSerializer(typeof(ValidatorList));
var test = "<..../>" // Your Xml
var xmlReader = XmlReader.Create(new StringReader(test));
var validatorList = (ValidatorList)ser.Deserialize(xmlReader);
There are many overrides of Deserialize which take differing inputs depending if the data is in a Stream an existing reader, or saved to a file.
You have to decorate the class that contains the _validators field with the KonwnType attribute
[Serializable]
[KwownType(typeof(RequiredFieldValidator)]
[KwownType(typeof(AsciValidator)]
public class MySerialisableClass
I have several SO answers that detail how to serialize objects using XML. I'll provide links below.
However, since you're looking for a rather simple serialization of your object, you may want to read up on the DataContractSerializer. It's much less complicated than the old .NET 1.x XML Serialization.
Here's the list of SO answers:
Omitting all xsi and xsd namespaces when serializing an object in .NET?
XmlSerializer: remove unnecessary xsi and xsd namespaces
Suppress xsi:nil but still show Empty Element when Serializing in .Net
Using XmlAttributeOverrides on Nested Properties
Even though many of these have to do with XML serialization and namespaces, they contain complete examples of serializing an object to XML using .NET 1.x XML Serialization.

DataContractSerializer not serializing one property

When I serialize the following class, the ContentPageId XML element is missing from the resulting XML file.
[CollectionDataContract(ItemName = "Widget")]
public sealed class StructurePage : List<Widget>, IEquatable<StructurePage>
{
[DataMember]
public int ContentPageId
{
get;
set;
}
public StructurePage(){}
public StructurePage(int pageId)
{
this.ContentPageId = pageId;
}
public bool Equals(StructurePage other)
{
return this.ContentPageId.Equals(other.ContentPageId);
}
}
Why is the property skipped when serializing and how to include it as XML element?
Is it possible to include it in serialization as an XML attribute to the StructurePage element? Was looking for this around the net but could find any info on it, apparently with XmlSerializer there was XmlAttributeAttribute attribute but no such thing with DataContractSerializer.
Go through this post http://social.msdn.microsoft.com/Forums/eu/wcf/thread/57eb195a-43a9-47fe-8b1a-a9d23feb2df2
According to this
Collection data contract classes cannot contain extra data members.
Hope this helps.

Categories