3

In my Controller I am converting XML data to JSON like this

 var doc = new XmlDocument();
 doc.Load(xmlStream);
 doc.DocumentElement.RemoveAttribute("xmlns"); // don't want xmlns node in json

 return Json(doc.DocumentElement.ChildNodes, new JsonSerializerSettings { StringEscapeHandling = StringEscapeHandling.Default }, Encoding.UTF8);

XML looks like this

<Employees xmlns="http://company.com/schemas">
    <Employee>
        <FirstName>name1</FirstName>
        <LastName>surname1</LastName>
    <Employee>
    <Employee>
        <FirstName>name2</FirstName>
        <LastName>surname2</LastName>
    <Employee>
    <Employee>
        <FirstName>name3</FirstName>
        <LastName>surname3</LastName>
    <Employee>
</Employees>

And output JSON

[
    {
        "Employee": {
            "FirstName": "name1",
            "LastName": "surname1"
         }
    },
    {
        "Employee": {
            "FirstName": "name2",
            "LastName": "surname2"
         }
    },{
        "Employee": {
            "FirstName": "name3",
            "LastName": "surname3"
         }
    }
]

What I want to achieve

[
    {
        "FirstName": "name1",
        "LastName": "surname1"
    },
    {
        "FirstName": "name2",
        "LastName": "surname2"
    },{
        "FirstName": "name3",
        "LastName": "surname3"
    }
]

So is there any way to convert XML element to JSON array while serializing it to JSON? I want to make this dynamic, so I do not want to write entity classes while doing that.

1
  • Can you share another example of xml (yours is not valid btw)? Commented Nov 3, 2017 at 14:02

3 Answers 3

2

I am not far what your expected output should be. I think we can do better, but here is my two lines solution:

Try it online!

var doc = XDocument.Parse(xmlData);
var json = JsonConvert.SerializeXNode(doc);

output:

{
  "Employees": {
    "@xmlns": "http://company.com/schemas",
    "Employee": [{
      "FirstName": "name1",
      "LastName": "surname1"
    }, {
      "FirstName": "name2",
      "LastName": "surname2"
    }, {
      "FirstName": "name3",
      "LastName": "surname3"
    }]
  }
}

Edit from @Peter:

Since schema is constant, it is possible to navigate the object to reach the object:

var employees = JObject.Parse(json).Children().Children().Children().ElementAt(1).Children().First();

Try it online!

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, that actually helped me. I just had to add var employees = JObject.Parse(json).Children().Children().Children().ElementAt(1).Children().First(); and I got exactly what I wanted. It might look is not that dynamic, but the xml structure will always be the same, only names will change, so it will work on all files that I have. Here is your edited fiddle link.
@Peter Glad to be helpful. I will add the line and the fiddle to the question.
0

It would be possible if you deserialize it in an object array before. Something like this:

    class Employee
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    static void DoXmlToJson()
    {
        string xmlData = @"<?xml version='1.0' encoding='UTF-8'?>
                          <Employees>
                            <Employee>
                                <FirstName>name1</FirstName>
                                <LastName>surname1</LastName>
                            </Employee>
                            <Employee>
                                <FirstName>name2</FirstName>
                                <LastName>surname2</LastName>
                            </Employee>
                            <Employee>
                                <FirstName>name3</FirstName>
                                <LastName>surname3</LastName>
                            </Employee>
                        </Employees>";

        XDocument doc = XDocument.Parse(xmlData);
        var array = doc.Root.Elements()
            .Select(row => new Employee() {
                FirstName = row.Element("FirstName").Value,
                LastName = row.Element("LastName").Value
            });

        string json = JsonConvert.SerializeObject(array);

        Console.WriteLine(json);
    }

Another way with using XmlSerializer.Deserialze:

    public class Employee
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    public class Employees
    {
        [XmlElement("Employee")]
        public Employee[] Items { get; set; }
    }

    static void DoXmlToJson()
    {
        string xmlData = @"<Employees>
                            <Employee>
                                <FirstName>name1</FirstName>
                                <LastName>surname1</LastName>
                            </Employee>
                            <Employee>
                                <FirstName>name2</FirstName>
                                //<LastName>surname2</LastName>
                            </Employee>
                            <Employee>
                                <FirstName>name3</FirstName>
                                <LastName>surname3</LastName>
                            </Employee>
                        </Employees>";


        XmlSerializer xmlSerializer = new XmlSerializer(typeof(Employees));
        MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData));
        Employees wholeObject = (Employees)xmlSerializer.Deserialize(memoryStream);

        string json = JsonConvert.SerializeObject(wholeObject.Items);

        Console.WriteLine(json);
    }

The ouput looks in both cases like this:

[
  {
    "FirstName": "name1",
    "LastName": "surname1"
  },
  {
    "FirstName": "name2",
    "LastName": "surname2"
  },
  {
    "FirstName": "name3",
    "LastName": "surname3"
  }
]

1 Comment

Well, as I said I want to make this dynamic so I do not want to write entity classes like "Employee" class.
0

With Cinchoo ETL - an open source library, you can do the Xml to Json easily with few lines of code

string xml = @"<Employees xmlns=""http://company.com/schemas"">
    <Employee>
        <FirstName>name1</FirstName>
        <LastName>surname1</LastName>
    </Employee>
    <Employee>
        <FirstName>name2</FirstName>
        <LastName>surname2</LastName>
    </Employee>
    <Employee>
        <FirstName>name3</FirstName>
        <LastName>surname3</LastName>
    </Employee>
</Employees>
";

StringBuilder sb = new StringBuilder();
using (var p = ChoXmlReader.LoadText(xml)
    )
{
    using (var w = new ChoJSONWriter(sb))
        w.Write(p);
}

Console.WriteLine(sb.ToString());

Output:

[
 {
  "FirstName": "name1",
  "LastName": "surname1"
 },
 {
  "FirstName": "name2",
  "LastName": "surname2"
 },
 {
  "FirstName": "name3",
  "LastName": "surname3"
 }
]

Checkout CodeProject article for some additional help.

Disclaimer: I'm the author of this library.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.