suryakiran
suryakiran

Reputation: 1996

Not getting the desired result upon converting XML to JSON String using JSON.Net

Following is the XML string which we are trying to convert in to JSON string.

  <?xml version="1.0" encoding="utf-16" ?> 
  <MyClass>
  <Id>1</Id> 
  <Names>
  <string>Surya</string> 
  <string>Kiran</string> 
  </Names>
  <ClassTypes>
  <Types>
  <TypeId>1</TypeId> 
  <TypeName>First Name</TypeName> 
  </Types>
  <Types>
  <TypeId>2</TypeId> 
  <TypeName>Last Name</TypeName> 
  </Types>
  </ClassTypes>
  <Status>1</Status> 
  </MyClass>

using the following code, I am getting the result as below

xmlString = "<?xml version=\"1.0\" encoding=\"utf-16\"?><MyClass><Id>1</Id><Names><string>Surya</string><string>Kiran</string></Names><ClassTypes><Types><TypeId>1</TypeId><TypeName>First Name</TypeName></Types><Types><TypeId>2</TypeId><TypeName>Last Name</TypeName></Types></ClassTypes><Status>1</Status></MyClass>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
doc.ChildNodes.OfType<XmlNode>().Where(x => x.NodeType == XmlNodeType.XmlDeclaration).ToList().ForEach(x => doc.RemoveChild(x));
jsonString = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None, true);

Actual Result

{"Id":"1","Names":{"string":["Surya","Kiran"]},"ClassTypes":{"Types":[{"TypeId":"1","TypeName":"First Name"},{"TypeId":"2","TypeName":"Last Name"}]},"Status":"1"}

Expected Result

{"Id":1,"Names":["Surya","Kiran"],"ClassTypes":[{"TypeId":1,"TypeName":"First Name"},{"TypeId":2,"TypeName":"Last Name"}],"Status":0}

We would require this result for deserialization to the below class

public class MyClass
{
    public int Id { get; set; }
    public IList<string> Names { get; protected set; }
    public IList<Types> ClassTypes { get; protected set; }
    public StatusType Status { get; set; }

    public MyClass()
    {
        Names = new List<string>();
        ClassTypes = new List<Types>();
        Status = StatusType.Active;
    }
}
public class Types
{
    public int TypeId { get; set; }
    public string TypeName { get; set; }
}

public enum StatusType
{
    Active = 0,
    InActive = 1
}

Upvotes: 0

Views: 672

Answers (1)

Arghya C
Arghya C

Reputation: 10078

You can use linq-to-xml. Try this code

var xmlString = "<?xml version=\"1.0\" encoding=\"utf-16\"?><MyClass><Id>1</Id><Names><string>Surya</string><string>Kiran</string></Names><ClassTypes><Types><TypeId>1</TypeId><TypeName>First Name</TypeName></Types><Types><TypeId>2</TypeId><TypeName>Last Name</TypeName></Types></ClassTypes><Status>1</Status></MyClass>";
XDocument doc = XDocument.Parse(xmlString);
XNode xNode = doc.FirstNode;
var jsonString = Newtonsoft.Json.JsonConvert.SerializeXNode(xNode, Newtonsoft.Json.Formatting.Indented, true);

Json string will be this

{
  "Id": "1",
  "Names": {
    "string": [
      "Surya",
      "Kiran"
    ]
  },
  "ClassTypes": {
    "Types": [
      {
        "TypeId": "1",
        "TypeName": "First Name"
      },
      {
        "TypeId": "2",
        "TypeName": "Last Name"
      }
    ]
  },
  "Status": "1"
}

UPDATE

Since OP has updated the question with classes, here is the alternative approach.

You can get properly formatted JSON with this code

var xmlString = "<?xml version=\"1.0\" encoding=\"utf-16\"?><MyClass><Id>1</Id><Names><string>Surya</string><string>Kiran</string></Names><ClassTypes><Types><TypeId>1</TypeId><TypeName>First Name</TypeName></Types><Types><TypeId>2</TypeId><TypeName>Last Name</TypeName></Types></ClassTypes><Status>1</Status></MyClass>";
var myClassObject = XmlDeserializeData<MyClass>(xmlString);
var jsonString = JsonSerializeData(myClassObject);

Here are my generic serialize/deserialize methods:

//using System.Xml.Serialization;
public T XmlDeserializeData<T>(string data)
{
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    StringReader reader = new StringReader(data);
    T result = (T)serializer.Deserialize(reader);
    return result;
}

//using Newtonsoft.Json
public string JsonSerializeData<T>(T data) 
{
    var serializedData = Newtonsoft.Json.JsonConvert.SerializeObject(data, Newtonsoft.Json.Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter());
    return serializedData; //notice the new Newtonsoft.Json.Converters.StringEnumConverter() to serialize enum as string
}

But, before this, you need to make following changes in your class

public class MyClass
{
    public int Id { get; set; }
    public List<string> Names { get; protected set; } //notice I changed from IList to List
    public List<Types> ClassTypes { get; protected set; } //IList doesn't work out of the box
    public StatusType Status { get; set; }

    public MyClass()
    {
        Names = new List<string>();
        ClassTypes = new List<Types>();
        Status = StatusType.Active;
    }
}

public enum StatusType //notice I added XmlEnum attribute, to serialize as 0, 1
{
    [XmlEnum(Name = "0")]
    Active = 0,
    [XmlEnum(Name = "1")]
    InActive = 1
}

And here is the generated JSON

{
  "Id": 1,
  "Names": [
    "Surya",
    "Kiran"
  ],
  "ClassTypes": [
    {
      "TypeId": 1,
      "TypeName": "First Name"
    },
    {
      "TypeId": 2,
      "TypeName": "Last Name"
    }
  ],
  "Status": "InActive"
}

UPDATE 2

Since you can not change the classes, and your XML is not 'ideal', you can do the following to get the desired JSON.

var xmlString = "<?xml version=\"1.0\" encoding=\"utf-16\"?><MyClass><Id>1</Id><Names><string>Surya</string><string>Kiran</string></Names><ClassTypes><Types><TypeId>1</TypeId><TypeName>First Name</TypeName></Types><Types><TypeId>2</TypeId><TypeName>Last Name</TypeName></Types></ClassTypes><Status>1</Status></MyClass>";

xmlString = xmlString.Replace("<ClassTypes>", "")
                    .Replace("</ClassTypes>", "")
                    .Replace("<Names>", "")
                    .Replace("</Names>", "");

xmlString = xmlString.Replace("<Types>", "<ClassTypes>")
            .Replace("</Types>", "</ClassTypes>")
            .Replace("<string>", "<Names>")
            .Replace("</string>", "</Names>");

var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);

var xmlNode = xmlDoc.SelectNodes("//MyClass").Item(0);
var jsonString = Newtonsoft.Json.JsonConvert.SerializeXmlNode(xmlNode, Newtonsoft.Json.Formatting.Indented, true);

Note It will generate the desired json, BUT this is a ugly hack! Either of the previous methods should be used.

Upvotes: 2

Related Questions