0

I have a piece of code that generate an XML base of a "template" file, all the data is dynamically taken from the project, base on current user..

And what i need to do, is to send JSON structure string to an API (i have no control on).

The problem which i am facing is that i can't manage to generate such a JSON(in the right format) from the XML using JsonConvert.SerializeObject.

With the help of an online tool i have creates this XML from that JSON, JsonConvert.SerializeObject(XML) generates a JSON, but instead, for example element that represent an array item - i need each item to be in [], RootDTO the root element, i don't need it at all.

So what i need to accomplish is turning this XML to a JSON that structured like that JSON.

Is it possible with the use of "json.net"? Do i need to write a "custom serilizer"


The XML i have:

<?xml version="1.0" encoding="UTF-8"?>
<RootDTO>
   <destination>
      <name>companyName</name>
   </destination>
   <orderData>
      <amount>123.45</amount>     
      <items>
         <element>            
            <binding>saddle</binding>
            <components>
               <element>                            
                  <width>210</width>
               </element>
            </components>
            <description>Introductory x</description>         
         </element>
      </items>
   </orderData>
</RootDTO>

The JSON JsonConvert.SerializeObject produce

{
   "?xml": {
      "@version": "1.0",
      "@encoding": "UTF-8"
   },
   "RootDTO": {
      "destination": {
         "name": "companyName"
      },
      "orderData": {
         "amount": "123.45",
         "items": {
            "element": {
               "binding": "saddle",
               "components": {
                  "element": {
                     "width": "210"
                  }
               },
               "description": "Introductory x"
            }
         }
      }
   }
} 

The desired JSON

{
   "destination": {
     "name": "companyName"
   },
   "orderData": {
      "amount": "123.45",
      "items": [
         {
            "binding": "saddle",
            "components": [
               {
                 "width": "210"
               }
            ],
            "description": "Introductory x"
         }
      ]
   }
}
dbc
  • 104,963
  • 20
  • 228
  • 340
Eran Meir
  • 923
  • 3
  • 17
  • 32
  • 2
    Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example. – mybirthname Jan 31 '16 at 16:24
  • What do you mean? i posted the init XML and the desired JSON, what i am asking, is how to parse it.. with the use of JSON.NET or other? how can i explain it better? – Eran Meir Jan 31 '16 at 16:27
  • this question has already been answered: [check this question](http://stackoverflow.com/questions/814001/convert-json-to-xml-or-xml-to-json-by-using-json-net) – Gerald V. Jan 31 '16 at 16:28
  • This is the only trouble code `JsonConvert.SerializeObject(XML)` and the xml + json, this is the only thing that i have posted - a brief as i could for making it understandably – Eran Meir Jan 31 '16 at 16:29
  • @Gerald V i know how to use JSON.NET, this is not the question- i want to customize the output – Eran Meir Jan 31 '16 at 16:30
  • Are you parsing the XML into an object? If so, all you have to do is JSON that object. – Mark PM Jan 31 '16 at 16:41
  • [`XmlNodeConverter`](http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Converters_XmlNodeConverter.htm) has properties [`DeserializeRootElementName`](http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Converters_XmlNodeConverter_DeserializeRootElementName.htm) and [`OmitRootObject`](http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Converters_XmlNodeConverter_OmitRootObject.htm) that may solve your *`RootDTO` the root element, i don't need it at all* issue. – dbc Jan 31 '16 at 17:24
  • But beyond that, can you show an example that is [as simple as possible](http://stackoverflow.com/help/mcve) of the XML you have, the JSON you are getting, and the JSON you want to get? It's unclear just from your written question and your linked JSON and XML where your problem lies. – dbc Jan 31 '16 at 17:25
  • @dbc i updated my question – Eran Meir Jan 31 '16 at 21:19
  • @EranMeir - the desired JSON in your question was invalid. You can see the error if you upload it to https://jsonformatter.curiousconcept.com/. I made a plausible fix since the error seemed unrelated to your conversion problems. If I fixed it wrongly, please update. – dbc Jan 31 '16 at 22:48

1 Answers1

1

You have a the following problems:

  1. You don't want the root element.

    That's easily removed, use JsonConvert.SerializeXNode Method(XObject, Formatting, omitRootObject = true) or set XmlNodeConverter.OmitRootObject = true.

  2. Elements are not coming back as JSON arrays.

    There is a basic inconsistency between XML and JSON in that XML does not have the concept of an array. It merely has sequences of elements with names. So, under what circumstances does Json.NET create arrays? From Converting between JSON and XML:

    Multiple nodes with the same name at the same level are grouped together into an array.

    However, what you have a two-level list, like so:

    <Container>
        <element>
        </element>
        <!-- Repeat as necessary -->
    </Container>
    

    Json.NET will not automatically recognize the container element as an array, thus you will need to pre-process the XML with LINQ to XML or post-process with LINQ to JSON. I think the latter is easier. Luckily, all your list entries are named element making the post-processing straightforward. It can be done with the following two extension methods:

    public static class JsonExtensions
    {
        public static JObject ToJObject(this XDocument xDoc)
        {
            // Convert to Linq to XML JObject
            var settings = new JsonSerializerSettings { Converters = new[] { new XmlNodeConverter { OmitRootObject = true } } };
            var root = JObject.FromObject(xDoc, JsonSerializer.CreateDefault(settings));
    
            // Convert two-level lists with "element" nodes to arrays.
            var groups = root.Descendants()
                .OfType<JProperty>()
                .Where(p => p.Name == "element")
                .GroupBy(p => (JObject)p.Parent)
                .Where(g => g.Key.Parent != null && g.Key.Properties().Count() == g.Count())
                .ToList();
            foreach (var g in groups)
            {
                // Remove values from properties to prevent cloning
                var values = g.Select(p => p.Value)
                    .SelectMany(v => v.Type == JTokenType.Array ? v.Children().AsEnumerable() : new[] { v })
                    .ToList()
                    .Select(v => v.RemoveFromLowestPossibleParent());
                g.Key.Replace(new JArray(values));
            }
            return root;
        }
    
        public static JToken RemoveFromLowestPossibleParent(this JToken node)
        {
            if (node == null)
                throw new ArgumentNullException("node");
            var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault();
            if (contained != null)
                contained.Remove();
            // Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
            if (node.Parent is JProperty)
                ((JProperty)node.Parent).Value = null;
            return node;
        }
    }
    

    Then just do:

        var xDoc = XDocument.Parse(xmlString);
        var root = xDoc.ToJObject();
        var jsonString = root.ToString();
    
dbc
  • 104,963
  • 20
  • 228
  • 340
  • Thanks @dbc - regarding the array that is not being created from XML->JSON, i encountered this post: [link](http://stackoverflow.com/questions/14488662/json-net-xml-serialization-misunderstands-arrays) it seems that if implement that solution, what left to do is to delete the `` tag, it's seems like it's more straightforward solution.. Can you give your opinion on this? – Eran Meir Feb 01 '16 at 08:03