NibblyPig
NibblyPig

Reputation: 52932

Convert XML without any attributes/metadata into a .NET object

I have an object, and I convert it to XML using a modified DataContractSerializer.

I strip out all the metadata/namespaces etc. so the result is just:

<myObject> <someProperty>5</someProperty> <mySubObjects> <mySubObject>...</mySubObject> <mySubObject>...</mySubObject> ... </myObject>

etc.

I wonder if it is possible to put this back into objects.

I was able to partially do it by using JSON.NET to convert it to JSon which works, but there is a problem with deserializing the JSon and Lists that I couldn't understand, despite reading several explanations about it on SO.

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None, true);
var obj = JsonConvert.DeserializeObject<T>(jsonText);

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type '...' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

There should be a more direct solution, there will never be an issue of trying to do an invalid cast as the source data is coming from the object too, some kind of mapping library or something should be able to take care of this. Any ideas?

Upvotes: 1

Views: 1222

Answers (1)

Cory
Cory

Reputation: 1802

Edit: Per the comments, here is how you would do it without having to convert to JSON

string xml = "<myObject>\n" +
             "  <someProperty>5</someProperty>\n" +
             "  <mySubObjects>\n" +
             "      <mySubObject>test</mySubObject>\n" +
             "      <mySubObject>test</mySubObject>\n" +
             "  </mySubObjects>\n" +
             "</myObject>\n";

using (TextReader reader = new StringReader(xml))
{
    XmlSerializer serializer = new XmlSerializer(typeof(myObject));
    var obj = serializer.Deserialize(reader);

}

Supporting class:

[Serializable()]
public class myObject
{
    [XmlElement("someProperty")]
    public string someProperty { get; set; }

    [XmlArray("mySubObjects")]
    [XmlArrayItem("mySubObject", typeof(string))]
    public List<string> mySubObjects { get; set; }
}

******Previous response using JSON:********

This code should do it for you:

string xml = "<myObject>\n" +
             "  <someProperty>5</someProperty>\n" +
             "  <mySubObjects>\n" +
             "      <mySubObject>test</mySubObject>\n" +
             "      <mySubObject>test</mySubObject>\n" +
             "  </mySubObjects>\n" +
             "</myObject>\n";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
var obj = JsonConvert.DeserializeObject<RootObject>(jsonText);

Here are the supporting classes:

public class MySubObjects
{
    public List<string> mySubObject { get; set; }
}

public class MyObject
{
    public string someProperty { get; set; }
    public MySubObjects mySubObjects { get; set; }
}

public class RootObject
{
    public MyObject myObject { get; set; }
}

The problem you were having is that it was trying to cast mySubObjects to an class instead of a List. This is because it sees each mySubObject as an object itself. By creating a class and exposing a List as a property, JSON.Net can then add each mySubObject to the exposed list. What it meant by changing it to a JSON array, is to take out the mySubObjects node completely, and just use multiple . JSON.Net would then see it as an array and convert it directly to a List instead of needing it to be encapsulated in a separate class. I hope I explained that correctly.

Upvotes: 1

Related Questions