2
1
0

Hi ,

I have a use case where I receive server output, from a Dynamic Data service call, in xml format and would like to convert it to JSON format.

Rather than hand craft a converter I was hoping to use a library and noticed that the Google Gson library is part of the 3rd Party Java Libraries included with TM.

However, I have not been able to find an example to use as a template to write the code.

The Gson documentation has examples of converting primitives and objects (an instance of a class). However, I have raw xml that does not have a defining class, so the xml is not 'strictly' a Java object.

Are there any resources available through Avoka documentation or other articles, or examples that I could use to get started?


Many Thanks

Mark

    CommentAdd your comment...

    5 answers

    1.  
      2
      1
      0

      Hi Mark

      Have you tried something like this?

      Cheers
      Rado

      import net.sf.json.JSON
      import net.sf.json.xml.XMLSerializer
      
      
      XMLSerializer xmlSerializer = new XMLSerializer()
      JSON json = xmlSerializer.read(xmlString)
      json.toString(2)
        CommentAdd your comment...
      1.  
        1
        0
        -1

        Hi,

        I found an example that uses XmlSlurper to convert xml to a Map. See https://stackoverflow.com/questions/26883223/xmlslurper-to-return-all-xml-elements-into-a-map

        It is generic, so can be applied to any xml.

        I tried to convert the code to use Path, instead of XmlSlurper, however I am having trouble with the class of the node that gets passed to the method during recursion.

        The method works on the first call, but fails when the childNode is passed to the method.

        import com.avoka.tm.util.Path
        import org.w3c.dom.Node
        import org.w3c.dom.NodeList
        
        def xml = '''<note>
        <to>Tove</to>
        <from>Jani</from>
        <heading>Reminder</heading>
        <body>Don't forget me this weekend!</body>
        <foot>
            <email>m@m.com</email>
            <sig>hello world</sig>
        </foot>
        </note>'''
        
        Path path = new Path(xml)
        
        List nodes = path.nodes("/*")
        
        def convertToMap = { Node root->
            Map member = [:]
        
            root.getChildNodes().findAll { Node child ->
                child.getNodeType() == (Short) 1
            }.each { item ->
                Node thisNode = (Node) item
                println thisNode.getClass()
                if (thisNode.getNodeType() == (Short) 1) {
                    //println item.getClass()
                    //member.put(thisNode.getNodeName(), thisNode.getTextContent())
                    member.put(thisNode.getNodeName(), thisNode.getChildNodes() ? convertToMap(thisNode) : thisNode.getTextContent())
                }
            }
            return member
        }
        
        def out = convertToMap(nodes[0])
        
        print out

        The error message is: Cannot find matching method Script1#convertToMap(org.w3c.dom.Node). Please check if the declared type is right and if the method exists.

        I'm wondering if the issue is the use of the w3c Node class, or whether it is an issue with the way Path handles the xml elements.

        This generic approach is exactly what I need, so that I can apply it to various xml structures without having to specify the element names.


        Any ideas of how to solve the class error?


        Thanks

        Mark

          CommentAdd your comment...
        1.  
          1
          0
          -1

          Hi All,

          thanks for the replies; lots of options to work with there.

          I did some more research last night and found some examples that use Groovy collect.

          I'll do some work on this and let you know what I end up with.

          Thanks again for all the feedback.


          Regards

          Mark

            CommentAdd your comment...
          1.  
            1
            0
            -1

            Hi Mark,

            If you need to transform the structure of the data while converting from XML to JSON, here is a sample from the documentation of the 17.10 release.  The bulk of the code will still work the same with earlier releases:

            FuncResult invoke(FuncParam param) {
                FormFuncResult result = new FormFuncResult()

                String message = param.svcDef.paramsMap.get('Soap Envelope')

                def response = new PostRequest(param.svcDef.svcConn.endpoint)
                    .setContentType('text/xml')
                    .setMessage(message).execute()

                if (!response.isStatusOK()) {
                    throw new RuntimeException(response.statusLine)
                }

                def countries = new Path(response.getPathContent().val('string'))
                    .paths('//Table[normalize-space(CurrencyCode) != ""]')

                result.data.put('success', true)
                result.data.put('countries', countries.collect {
                    [
                        Name : it.val('//Name'),
                        CountryCode : it.val('//CountryCode').toString().toUpperCase(),
                        CurrencyCode: it.val('//CurrencyCode').toString().toUpperCase(),
                    ]
                })

                return result

            This particular code pulls a list of country codes from http://www.webservicex.net/New/Home/ServiceDetail/17 and filters the list to remove entries with blank currency codes.

            Because Groovy services don't support GPath, the code makes use of the SDK Path object documented at Path, and Groovy collect. There is some helpful info about Groovy collect at http://mrhaki.blogspot.com.au/2011/09/groovy-goodness-collect-on-nested.html 

            Using Path in conjunction with collect allows you to write very tightly-coded and nicely readable transforms.

              CommentAdd your comment...
            1.  
              1
              0
              -1

              Hi Mark,

              Also have you considered using XmlSlurper?  We use it quite often and it's a good tool to help Xml parsing.  Search in Google for examples which may give you what you need.

              For instance:

              https://stackoverflow.com/questions/23374652/xml-to-json-with-groovy-xmlslurper-and-jsonbuilder

                CommentAdd your comment...