Response value of an API is a plaintext, can I create a list from it?

Greetings everyone, just like the title state, I have an API that has a plaintext response format for our mobile app. I found this is quite a problem since I cannot deserialize because the response data type is a plaintext. It looks like this:

Based on the picture, can I create a list from that JSON format type? Do I have to eliminate several characters first such as "\" or misplaced double quote symbol before append it to a list? Thank you.

Hi Adyita,

This seems like JSON that has been turned into a string. Do you know why the API sends it like this? Are the backslashes actually inside the string, or is this just Postman displaying them?

I would advise you to consume the API in OutSystems, and check whether this is the actual API output.

Kilian Hekhuis wrote:

Hi Adyita,

This seems like JSON that has been turned into a string. Do you know why the API sends it like this? Are the backslashes actually inside the string, or is this just Postman displaying them?

I would advise you to consume the API in OutSystems, and check whether this is the actual API output.

Hi Kilian, yes this is the actual output. I've consumed it using POST method with authorization.

This API is also used in another mobile application, but not within Outsystems platform. I want to know if this response format can be processed to the OS structure entity, or maybe there is a workaround to create a list based on this API? Thanks

Really, really weird. Anyways, you could just apply a Replace to replace the \" with a ". To do so, keep in mind that a single double quote is represented by two double quotes:

Replace(Input, "\""", """")

Then you have something you can apply a JSON Deserialize () to.

Kilian Hekhuis wrote:

Really, really weird. Anyways, you could just apply a Replace to replace the \" with a ". To do so, keep in mind that a single double quote is represented by two double quotes:

Replace(Input, "\""", """")

Then you have something you can apply a JSON Deserialize () to.

I've tried this flow when fetching the data. I have also removed the double quote in the beginning and the end:



The response format is a plaintext, is it still can be serialized other than JSON response format?

Hi Aditya Eka Prabowo,

As Kilian Hekhuis suggested, replace '\"' with '"', create a structure as per the JSON and use JSON Deserialize to get the object. Just make sure that 'Name of Json' of the structure column is the same as the node name in JSON.

Hi Aditya,

That's exactly what Deserializing means, you have Text in JSON format, and you deserialize it into Structures. To automatically create the structures, you can copy/paste the JSON (replace the \" in a Notepad++ or some other editor) when consuming the REST service, and modify the actual input afterwards.

Hi pranav pandey & Kilian Hekhuis, ok now I already created the structure after the \" and double quote removal. Now since I want to create a list based on the structure, is this correct on how to do it? I append it on a local variable list: 


When I tried the debug, it just passed the both of deserialize process and straight to the end.. is this because the response of the API is not a structure (instead a plaintext)? Do I have to modify the response as a JSON format first?

Note: this is on a mobile application.

also, when the process try to deserialize the response value become empty: 

This is the properties of the Deserialize process:

Hi Aditya Eka Prabowo,

Question 

what exactly are you getting from the API call, I mean does your API response JSON string contains multiple data of that same structure or just one?

if its multiple the structure definition should of type list of that structure.

Also, the steps that you are doing is not correct. As per what I understand, your response will be of type list of object in JSON string . just deserialize the data to object and assign it to your local variable list. You don't need to run a loop and deserialize it again.

It will be better if you provide a sample of the JSON response that you will be getting from the API(not the screenshot).


pranav pandey wrote:

Hi Aditya Eka Prabowo,

Question 

what exactly are you getting from the API call, I mean does your API response JSON string contains multiple data of that same structure or just one?

if its multiple the structure definition should of type list of that structure.

Also, the steps that you are doing is not correct. As per what I understand, your response will be of type list of object in JSON string . just deserialize the data to object and assign it to your local variable list. You don't need to run a loop and deserialize it again.

It will be better if you provide a sample of the JSON response that you will be getting from the API(not the screenshot).


Hi Pranav, yes as I said before, the platform catched the response as a plaintext not a JSON list.. that's why I try to create a loop in the logic flow.


 okay here is the sample response:

"{\"20200623070939\":{\"absensi_date\":\"23-JUN-2020\",\"hour_in\":\"23-JUN-2020 07:09:39\",\"hour_out\":null,\"reason\":\"Clock In: A \\n\\nClock Out:\",\"clock_in_ip\":\"180.251.220.129\",\"clock_out_ip\":\"180.251.220.129\",\"flag_late\":null,\"flag_early\":null,\"in_lat\":\"-6.2133198\",\"in_long\":\"106.3766966\",\"in_out_office\":1,\"out_lat\":null,\"out_long\":null,\"out_out_office\":null,\"status\":\"waiting clockout\",\"status_clock_in\":\"complete\",\"status_clock_out\":null},\"20200619114321\":{\"absensi_date\":\"19-JUN-2020\",\"hour_in\":\"19-JUN-2020 11:43:21\",\"hour_out\":null,\"reason\":\"Clock In: A \\n\\nClock Out:\",\"clock_in_ip\":\"182.0.240.209\",\"clock_out_ip\":\"182.0.240.209\",\"flag_late\":\"Y\",\"flag_early\":null,\"in_lat\":\"-6.2133015\",\"in_long\":\"106.3766805\",\"in_out_office\":1,\"out_lat\":null,\"out_long\":null,\"out_out_office\":null,\"status\":\"waiting clockout\",\"status_clock_in\":\"complete\",\"status_clock_out\":null}}"


it's before I remove the unused strings, and here after it does:


{"20200623070939":{"absensi_date":"23-JUN-2020","hour_in":"23-JUN-2020 07:09:39","hour_out":null,"reason":"Clock In: A \\n\\nClock Out:","clock_in_ip":"180.251.220.129","clock_out_ip":"180.251.220.129","flag_late":null,"flag_early":null,"in_lat":"-6.2133198","in_long":"106.3766966","in_out_office":1,"out_lat":null,"out_long":null,"out_out_office":null,"status":"waiting clockout","status_clock_in":"complete","status_clock_out":null},"20200619114321":{"absensi_date":"19-JUN-2020","hour_in":"19-JUN-2020 11:43:21","hour_out":null,"reason":"Clock In: A \\n\\nClock Out:","clock_in_ip":"182.0.240.209","clock_out_ip":"182.0.240.209","flag_late":"Y","flag_early":null,"in_lat":"-6.2133015","in_long":"106.3766805","in_out_office":1,"out_lat":null,"out_long":null,"out_out_office":null,"status":"waiting clockout","status_clock_in":"complete","status_clock_out":null}}


Hi, 

I think you will have to manipulate further your response, because actually, it seems like an object with multiple attributes:

20200623070939

and

20200619114321

But I don't think you can handle this in OutSystems. 

You can change it to a list replacing the outer {} by []. Your structure will have to change as well. And I think (not sure here), that the datetime that currently is the attribute label will have to be nirmalized to have always the same name... 

Hi Aditya Eka Prabowo,

I checked and found that decoding it is a little tricky here your innermost data structure is constant but the node to which it is attached to it changing (basically its a value).

{
"20200623070939": {
"absensi_date": "23-JUN-2020",
"hour_in": "23-JUN-2020 07:09:39",
"hour_out": null,
"reason": "Clock In: A \\n\\nClock Out:",
"clock_in_ip": "180.251.220.129",
"clock_out_ip": "180.251.220.129",
"flag_late": null,
"flag_early": null,
"in_lat": "-6.2133198",
"in_long": "106.3766966",
"in_out_office": 1,
"out_lat": null,
"out_long": null,
"out_out_office": null,
"status": "waiting clockout",
"status_clock_in": "complete",
"status_clock_out": null

},
"20200619114321": {
"absensi_date": "19-JUN-2020",
"hour_in": "19-JUN-2020 11:43:21",
"hour_out": null,
"reason": "Clock In: A \\n\\nClock Out:",
"clock_in_ip": "182.0.240.209",
"clock_out_ip": "182.0.240.209",
"flag_late": "Y",
"flag_early": null,
"in_lat": "-6.2133015",
"in_long": "106.3766805",
"in_out_office": 1,
"out_lat": null,
"out_long": null,
"out_out_office": null,
"status": "waiting clockout",
"status_clock_in": "complete",
"status_clock_out": null

}
}

Let me try to find a solution.

I agree with Eduardo, I didn't see the variable lables at first, but they need to go; luckily they don't contain any useful information. I'll upload a simple OML that does that in a minute...

Ok, I was not able to create a structure for it. 

it have been possible if the structure would be in below mention form.
1: Put the node data in the inner structure
{
{
"header":"20200623070939",
"absensi_date": "23-JUN-2020",
"hour_in": "23-JUN-2020 07:09:39",
"hour_out": null,
"reason": "Clock In: A \\n\\nClock Out:",
"clock_in_ip": "180.251.220.129",
"clock_out_ip": "180.251.220.129",
"flag_late": null,
"flag_early": null,
"in_lat": "-6.2133198",
"in_long": "106.3766966",
"in_out_office": 1,
"out_lat": null,
"out_long": null,
"out_out_office": null,
"status": "waiting clockout",
"status_clock_in": "complete",
"status_clock_out": null
},
{
"header":"20200619114321",
"absensi_date": "19-JUN-2020",
"hour_in": "19-JUN-2020 11:43:21",
"hour_out": null,
"reason": "Clock In: A \\n\\nClock Out:",
"clock_in_ip": "182.0.240.209",
"clock_out_ip": "182.0.240.209",
"flag_late": "Y",
"flag_early": null,
"in_lat": "-6.2133015",
"in_long": "106.3766805",
"in_out_office": 1,
"out_lat": null,
"out_long": null,
"out_out_office": null,
"status": "waiting clockout",
"status_clock_in": "complete",
"status_clock_out": null
}
}

2: Create the inner data as nested structure as follows
{
"parent":"20200623070939",
"column": {
"absensi_date": "23-JUN-2020",
"hour_in": "23-JUN-2020 07:09:39",
"hour_out": null,
"reason": "Clock In: A \\n\\nClock Out:",
"clock_in_ip": "180.251.220.129",
"clock_out_ip": "180.251.220.129",
"flag_late": null,
"flag_early": null,
"in_lat": "-6.2133198",
"in_long": "106.3766966",
"in_out_office": 1,
"out_lat": null,
"out_long": null,
"out_out_office": null,
"status": "waiting clockout",
"status_clock_in": "complete",
"status_clock_out": null
},
"parent":"20200619114321",
"column": {
"absensi_date": "19-JUN-2020",
"hour_in": "19-JUN-2020 11:43:21",
"hour_out": null,
"reason": "Clock In: A \\n\\nClock Out:",
"clock_in_ip": "182.0.240.209",
"clock_out_ip": "182.0.240.209",
"flag_late": "Y",
"flag_early": null,
"in_lat": "-6.2133015",
"in_long": "106.3766805",
"in_out_office": 1,
"out_lat": null,
"out_long": null,
"out_out_office": null,
"status": "waiting clockout",
"status_clock_in": "complete",
"status_clock_out": null
}
}

Solution

Hi Aditya,

Find a solution attached. I convert the JSON to an array, then remove the variable attribute names. This allows you to convert it to a List with DeserializeJson. You'll probably want to do some more conversion, like convert the dates and date/times to proper OutSystems Date and DateTime variables, but I think you can handle that?


Solution

Tried Kilian solution, Worked like a charm.

btw, good idea of removing that parent number node .

:)

Kilian Hekhuis wrote:

Hi Aditya,

Find a solution attached. I convert the JSON to an array, then remove the variable attribute names. This allows you to convert it to a List with DeserializeJson. You'll probably want to do some more conversion, like convert the dates and date/times to proper OutSystems Date and DateTime variables, but I think you can handle that?


Hi Killian, I really thankful for your help, I really appreciate it :)

However I don't adjust the value to our API's return value yet. I'll let you know once it's done.

Hello everyone, I really appreciate all the answers and responses, this problem is solved :) Thanks Kilian Hekhuis for giving a wonderful example method. 

By the way, i got a small question, how to remove the last character in a text value? i try to use this syntax but turns out it removed all the strings: 

Am I wrong? 

Once again, thanks everyone that have contributed on this post

Hi Adyita,

You're most welcome, glad I could be of help.

The second parameter of Substr is the starting index, so you take everything starting with the first character after the string :). So it should be:

Substr(CustomizedResponse.ResponseText, 0, Length(CustomizedResponse.ResponseText) - 1)