Deserialize a dynamic JSON object

Deserialize a dynamic JSON object

  

Hello,

I'm trying to request a JSON object via RESTful API but the problem is that the attributes can be dynamic. Therefore I can't define a structure beforehand because I don't know the items in the Json response object yet. 

So for example: I make a GET request to the API, the API responds with this format:

{
    "conditions": [ {
        "conditionvalue": {
            "pattern": "somethinghere"
        }
    }],
    "contentExpression": {
        "id": "somethinghere"
    }
}

The problem is that "conditions" can be 1 or more objects of type "conditionvalue" AND "conditionvalue" can have various names defined by the user.

Is there a way to fix or workaround this issue?

Hi Joeri,

The way we already solved this issue is using the OnAfterRequest action to edit the JSon returned to fit the existing structure.

For example, if the element can be a single value or a list, we put a list in the structure and pre process the json to change the element to list if it came single.

Cheers,

Eduardo Jauch

Hello, thank you for your reply! I couldn't find the "OnAfterRequest" action anywhere unfortunately. Can you tell me where I should search? I forgot to mention btw that this is a web application. 

(I'm only a very beginner level user of Outsystems so sorry if I'm asking trivial questions)

Ok got it. But now is the next problem: you said you can edit the JSon returned to fit the existing structure but I want it the other way round (edit a structure to fit the returned JSON). How can I do that? Because of the fact that my JSON responses can vary I cannot define one structure that can hold all attributes.

For example: one time the response looks like this:

{
    "conditions": [{
        "dynamicName1": {
            "pattern": "test1"
        },

        "dynamicName2": {
            "pattern": "test2"
        }
    }],
    "contentExpression": {
        "id": "somethingstatic"
    }
}

And another response with the same call can look like this:

{
    "conditions": [{
        "anotherDynamicName1": {
            "pattern": "test1"
        },

        "anotherDynamicName2": {
            "pattern": "test2"
        },

        "anotherDynamicName3": {
            "pattern": "test3"
        }
    }],
    "contentExpression": {
        "id": "somethingstatic"
    }
}


So as you can see, in my usecase you can say that a response is kind of unique, so I can't design a structure beforehand. 

Hi,

There is no way to create dynamic structures.

You can try to make your json fit a generic structure, or you can process your json manually and store info somewhere.

To a structure to be used in OutSystems, it mist be known at design time.

Let me ask you something. How do you expect to use a structure, in your code, that you don't know what are its fields and types beforehand?

How do you expect to use your structure in your code?

Cheers

Eduardo Jauch

Ok, J. Is providing a way to change your structure. Into something known.

But you will have to process field by field.

There is no way to create dynamic structures.

Cheers

Eduardo Jauch

Thank you both for the replies. I will check ardoJSON out. Is there any guide on how to use the Listify function as that seems what I need? 

And I don't quite understand how to edit the JSON in the response in the OnAfterResponse action. I cannot find the JSON object which was sent in the response where can I find that so I can alter it?

Solution

Hello,

In the Response.ResponseText you will find the JSON that was returned by the web service.
You must set the JSON in the CustomizedResponse.ResponseText.



But of course, you can manipulate the JSON. For example, my consumed web service in the attached example is expecting a LIST, but I will ask the web service I made to return an object. What I'll do is to check if the response is a list, if not, I'll "fix" it to be one. This way, the answer returned to the code will fit my expectation. 

With this approach, if you know which fields can being received as list or single fields, you can process your json to match the result.

BUT...

If your problem is that you will receive fields with "dynamic" names (??????), how will you even use them? There is any rule you can apply to change them into a form that you can effectively use?

In any case, you could do something similar to what Listfy does, that is convert the array of fields into something like this: 

{
    "conditions": [{
        "key": "anotherDynamicName1",
        "value": {
            "pattern": "test1"
        },

        "key": "anotherDynamicName2",
        "value": {
            "pattern": "test2"
        },

        "key" : "anotherDynamicName3",
        "value": {
            "pattern": "test3"
        }
    }],
    "contentExpression": {
        "id": "somethingstatic"
    }
}

If you process your json this way, you can have a structure where "conditions" is a list of an object of the form "key, value", where value is another object of type "pattern, value".

I don't know if you can use listfy from ARDOJSON here, but certainly you can create a pre-processor that can handle this.

Cheers,
Eduardo Jauch

EDIT

Link for the example: https://eduardojauch.outsystemscloud.com/OnAfterResponseTest/HomeScreen.aspx

Solution

This is exactly what I needed, thanks! We have redesigned our API to return JSON in the format of key-value pairs and now we can use the data flawlessly. 

"If your problem is that you will receive fields with "dynamic" names (??????), how will you even use them? "

This was an issue indeed and we hadn't considered that yet. But now with this method it completely removes this obstacle :)

Thanks again for your help!

Joeri Klomp wrote:

This is exactly what I needed, thanks! We have redesigned our API to return JSON in the format of key-value pairs and now we can use the data flawlessly. 

"If your problem is that you will receive fields with "dynamic" names (??????), how will you even use them? "

This was an issue indeed and we hadn't considered that yet. But now with this method it completely removes this obstacle :)

Thanks again for your help!

Hi! :)

Thats good to hear :)
If any of the questions were good to help you solve the problem, please, mark one of them as correct, to help others searching the forum and facing the same problem to find the answer quickly

Cheers,
Eduardo Jauch