0

My requirement is to parse through numerous backend responses, which can be either json or xml. Their response structure is not known to me now. So, i have to write a java tool in a such a way that, my tool should be able to parse through the response based on the configuration file, which will be configured by the services team before they run my tool as they will get to know the values, they will have to retrieve via my tool. For instance, if backend json or xml response looks like below and my configuration says Employee.details.referenced[0].type, the value retrieved via tool should be 'customer-support'. I will not be able to use pojo or something, which is coupled to the backend response as i will not know the backend response and my same tool should work for different backends, which output response in different structure:

Json:

{
    "Employee": [
        {
            "id": "12345678",
            "service": "ps",
            "origin": {
                "address": {
                    "addressLocality": "India"
                }
            },
            "destination": {
                "address": {
                    "addressLocality": "US"
                }
            },
            "status": {
                "timestamp": "2019-01-29T21:02:49Z",
                "location": {
                    "address": {
                        "addressLocality": "Germany"
                    }
                },
                "Code": "xyz",
                "description": "Services"
            },
            "details": {
                "references": [
                    {
                        "number": "0003030891",
                        "type": "customer-support"
                    }
                ]
            }
        }
    ]
}

XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <Employee>
      <element>
         <destination>
            <address>
               <addressLocality>US</addressLocality>
            </address>
         </destination>
         <details>
            <references>
               <element>
                  <number>0003030891</number>
                  <type>customer-support</type>
               </element>
            </references>
         </details>
         <id>12345678</id>
         <origin>
            <address>
               <addressLocality>India</addressLocality>
            </address>
         </origin>
         <service>ps</service>
         <status>
            <Code>xyz</Code>
            <description>Services</description>
            <location>
               <address>
                  <addressLocality>Germany</addressLocality>
               </address>
            </location>
            <timestamp>2019-01-29T21:02:49Z</timestamp>
         </status>
      </element>
   </Employee>
</root>

I tried to check on json parsers in java and xml saxparser. But, all seems to be bound to know the backend response in advance.

ANITHA
  • 37
  • 7
  • Use `Map` then if you don't know the response structure. – Tayyab Razaq May 22 '19 at 06:36
  • `javax.json.Json` and `javax.xml.parsers.DocumentBuilder` work on JSON respectively XML objects instead of mapped objects. – Smutje May 22 '19 at 06:41
  • With respect to parsing the XML documents: There is already a standard to traverse XML documents called XPath, so maybe you aren't forced to re-invent the wheel. – Smutje May 22 '19 at 06:44
  • @Smutje Using javax.json.Json is there a way i can parse through the response json or xml without creating a pojo class of say Employee? – ANITHA May 22 '19 at 06:58
  • Have you even checked the documentation? Spoiler: Yes, you can. – Smutje May 22 '19 at 07:25

2 Answers2

1

Jackson can parse both JSON and XML to Map<String, Object>. value is typed Object since, besides String property it can be List or also Map that represents JSON/XML sub tree

Sharon Ben Asher
  • 13,849
  • 5
  • 33
  • 47
1

Another poster has already pointed out the Jackson library, but I'd like to add my thoughts:

Jackson is capable of parsing a String (or any other of several I/O sources) directly into a JsonNode:

String json = backEndProvider.fetch(); // example call
JsonNode node = new ObjectMapper().readTree(json);

You may then access children of the resulting JsonNode using its .get() method:

JsonNode child = node.get("childKey");

Furthermore, terminal values can be accessed using a wide variety of conversion methods. For example, if you knew child was textual, you could get child's value in the following way:

String childValue = child.asText();

See also this Baeldung article.

From here, you can parse your user's input String (say Employee.details.referenced[0].type) into a key array (such as ["Employee", "details", "referenced[0]", "type"]) and recursively access your root element until you fetch the adequate value, checking at each stage if the key is an array access operation. You will need to return a JsonNode or an Object from your reference resolver if you have no type information whatsoever.

For array accesses such as referenced[0], note ArrayNode inhertits ObjectNode and its get() method is overriden to use an int.

Note the solution above works just the same with Jackson's XmlMapper.

Paul Benn
  • 1,911
  • 11
  • 26
  • Thanks a lot! It did work for my json parsing. But, with xml parsing i am doing something like this: new XmlMapper().readTree(xmlString); But, this is internally converted to json. But, when i see wrt to arrays, the value what it has only the last indexed value. I mean say my input xml is as below: – ANITHA May 22 '19 at 12:42
  • 4.0.0 com.test com.fasterxml.jackson.core jackson-databind 2.2.3 com.fasterxml jackson-xml-databind 0.6.2 – ANITHA May 22 '19 at 12:45
  • The internally converted Json looks like as below, when I debug my code. Why is it this way? { "modelVersion": "4.0.0", "groupId": "com.narvar", "artifactId": "carrier-integration", "version": "1.0.0", "dependencies": { "dependency": { "groupId": "com.fasterxml", "artifactId": "jackson-xml-databind", "version": "0.6.2" } } } Under dependencies values are missing. – ANITHA May 22 '19 at 12:45
  • I got this working for xml parsing as well. Wrt to Jackson XmlMapper there seems to be an issue when complex xml is parsed. So, i used org.json.XML toJsonObject function to convert XML to JSON as per the solution provided in https://stackoverflow.com/questions/1823264/quickest-way-to-convert-xml-to-json-in-java . Thanks all for the support! – ANITHA May 23 '19 at 07:35