cancel
Showing results for 
Search instead for 
Did you mean: 

Error While converting JSON to XML in SAP CPI/CI

0 Kudos
2,432

Hi Experts,

I'm working on a scenario where I'm receiving JSON input and would like to convert it into XML and push it to S4 HANA system. When I use the standard JSON to XML convertor , I receive the below error as the sender system is not sending the JSON in proper format. Sender is not ready to handle this at their end and needs to be handled in the middleware.

In such a scenario , Could someone guide me how this can be handled please?

Incoming JSON from Sender System: (incorrect format due to missing double quotes for date BEGDA & ENDDA)

{"I_BEGDA":2020-01-01,"I_ENDDA":2020-01-21,"I_TOTAL":"X"}

Error While using Standard convertor:

com.sap.it.rt.adapter.http.api.exception.HttpResponseException: An internal server error occured: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 12 path $.I_BEGDA

Can any one guide me how this JSON can be converted to the correct JSON format please?

Correct JSON expected as input to the standard convertor

{"I_BEGDA":"2020-01-01","I_ENDDA":"2020-01-21","I_TOTAL":"X"}

Highly appreciate your responses

Thanks,

Priyanka

Accepted Solutions (1)

Accepted Solutions (1)

donepuna
Advisor
Advisor
0 Kudos

Hi Priyanka,

You can add a Groovy script before "JSON To XML Convertor" and add below code.

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.lang.String;

def Message processData(Message message) {
    def input = message.getBody();

    def BEGDA = "\"I_BEGDA\":";
    def ENDDA = "\"I_ENDDA\":";

    def BDt_StartIndex = input.indexOf(BEGDA);
    def BDt_EndIndex = BDt_StartIndex+20;
    def BDT = input.substring(BDt_StartIndex+10,BDt_EndIndex);
    def output = input.replace(BDT,'\"'+BDT+'\"');
    
    def EDt_StartIndex = input.indexOf(ENDDA);
    def EDt_EndIndex = EDt_StartIndex+20;
    def EDT = input.substring(EDt_StartIndex+10,EDt_EndIndex);
    output = output.replace(EDT,'\"'+EDT+'\"');
    
    message.setBody(output);
 
  return message;
}

Note: This sample code works for single record, if you have multiple records then you have to enhance this code further. This is just to give an idea.

input: {"I_BEGDA":2020-01-01,"I_ENDDA":2020-01-21,"I_TOTAL":"X"}

output: {"I_BEGDA":"2020-01-01","I_ENDDA":"2020-01-21","I_TOTAL":"X"}

Thanks

Nagesh

0 Kudos

Hi Nagesh

@donepuna,

Thanks much for your response. Highly appreciate.

When I run this code in CI, I get the below error in the groovy script step. Could you kindly help with this please?

Error:

No signature of method: org.apache.camel.converter.stream.InputStreamCache.indexOf() is applicable for argument types: (java.lang.String) values: ["I_BEGDA":]

Possible solutions: inMemory(), findIndexOf(groovy.lang.Closure), inject(groovy.lang.Closure)

Thanks,

Priyanka

Answers (3)

Answers (3)

lalit2054_46
Participant
0 Kudos

Hi priyanka_ajn1992_90

Below is much cleaner option using Groovy Script and you get directly an xml output -

import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.xml.*

def Message processData(Message message) {
    
    def body = message.getBody(java.lang.String) as String
    def I_BEGDA_VAL = (body =~ /I_BEGDA":(.*?)[,]/)[0][1]
    def I_ENDDA_VAL = (body =~ /I_ENDDA":(.*?)[,]/)[0][1]
    def I_TOTAL_VAL = (body =~ /I_TOTAL":"(.*?)["]/)[0][1]

    
    def writer = new StringWriter()
    def xml = new MarkupBuilder(writer) 
    xml.xml() {
        I_BEGDA(I_BEGDA_VAL)
        I_ENDDA(I_ENDDA_VAL)
        I_TOTAL(I_TOTAL_VAL)
    
    }

    message.setBody(writer.toString())
    return message;
}

0 Kudos

Hi donepuna , priyanka2018 ,

Thanks much for the help above. Everything working as expected with the code above apart from one scenario. When the I_BEGDA & I_ENDDA values are the same, The script does not work as expected. Any clues here how to rectify this please?

Ex :{"I_BEGDA":2020-01-01,"I_ENDDA":2020-01-01,"I_TOTAL":"X"}

With this input, I'm getting additional double quotes. Request your kind help .

Output :

{"I_BEGDA":""2020-01-01"","I_ENDDA":""2020-01-01"","I_TOTAL":"X"}

Thanks,

Priyanka

PriyankaChak
Active Contributor
0 Kudos

Hi Priyanka,

You can change the first line to below and use Nageswara's code and it will work.

def input = message.getBody(String);

0 Kudos

Thank you so much Priyanka. It worked 🙂

Regards,

Priyanka