engswee / equalize-cpi-converter

CPI Converter a.k.a. FormatConversionBean for CPI
MIT License
17 stars 9 forks source link

XML2JSON Converter when there are two xml nodes with same name but one is array #5

Closed baroni2019 closed 4 years ago

baroni2019 commented 4 years ago

Hi Eng Swee Yeoh. I've got an use case where a XML to be converted to JSON has two XML nodes with same name, one should be array and the other not. Given that I am not able to use arrayFieldList as it would change the two nodes to array in JSON. So I would like to suggest using XPATH instead of NomeName in the arrayFieldList parameter, so it would be possible to define only one Node to be JSON array and other not. Example below regarding of "customFields":

XML:

<test>
  <customFields>
     <fields>123</fields>
     <fields>456</fields>
   </customFields>
   <customer>
      <customFields>abc<customFields>
      <customFields>def<customFields>
   </customer>

Desired JSON:

{
   "test" : {
      "customFields" : {
         "fields": [ "123", "456" ]
      },
      "customer": {
         "customFields": [ "abc", "def" ]
      }
   }
}

Kind Regards.

Pedro Baroni

engswee commented 4 years ago

Hi Pedro, using XPath to determine the node that needs to be forced as an array is indeed a more flexible approach.

However, based on your particular example on customFields, I don’t think you need it. The first occurrence only happens once, while the second occurrence happens twice. Have you tried the conversion without setting arrayFieldList value? That is only useful if you want to explicitly force it to be an array. Otherwise it automatically determines if it should be an array or not based on the occurrence in the payload.

baroni2019 commented 4 years ago

Hi Swee, thanks for your reply.

Actually I do have the situation below as well, where wouldn't work based on the occurrence:

XML:

<test>
  <customFields>
     <fields>123</fields>
     <fields>456</fields>
   </customFields>
   <customer>
      <customFields>abc<customFields>
   </customer>

Desired JSON:

{
   "test" : {
      "customFields" : {
         "fields": [ "123", "456" ]
      },
      "customer": {
         "customFields": [ "abc" ]
      }
   }
}
engswee commented 4 years ago

Hi Pedro

I have released a new version 2.2.0 whereby the JSON processing has been switched to using Groovy's built-in JSON capability. Alongside that, I have added new parameter arrayGPathList to cater for your scenario. The parameter works based on GPath of the target JSON structure, instead of XPath of the source XML structure.

For your case, you can configure it like: arrayGPathList = test.customer.customFields You can refer to the test case in the following Spock specification too https://github.com/engswee/equalize-cpi-converter/blob/master/src/test/groovy/com/equalize/converter/core/XML2JSONConverterSpec.groovy

Give it a try and let me know how it goes.

baroni2019 commented 4 years ago

Hi,

Working perfectly, thank you. My actual scenario is Integration between SAP ECC and DocuSign (Envelopes) via SAP CPI. SAP ECC side is ABAP Proxy (totally XML XI Adapter). DocuSign REST APIs using JSON. In POST Envelope data model there are about 4.000 (yes, four thousand) fields. With some repetitive fieldNames in different formats (p.e. String and Array). Reference: (DocuSign Envelope Creation REST API) This brand new "arrayGPathList" helped me a lot and solved the problem quite straightforward. Look forward to seeing SAP Blog updates.

Many many thanks.

Pedro Baroni

engswee commented 4 years ago

Great to hear that it is working now. The reference blog has also been updated. I'll close this issue.