Nested JSON always ends up as list in app data

Hi,

Currently struggling a lot to get this working:
I have a workflow where (after user clicks a button on frontend), an API call is made. The response is a nested JSON with hotel data, with below structure, but then for each hotel available. So note the screenshot shows only 1 hotel, but there can be multiple.

I want to store the Hotel Name & Price (both parameters are available in the JSON) in a custom state, so this can be displayed to the user in a Repeating Group. Though, I am unable to get one single hotel and one single price per row in the app data table, it always ends up everything as a list in the same row, comma separated. So e.g.

[column 1] ----------------------------- [column 2]
[Hotel A, Hotel B, Hotel C] --------[Price A, Price B, Price C]

There is no action in the workflow where I can select dynamic data “Current item”, it will always show “Each item”, resulting in this becoming lists.

Can anyone help out how to deal with this the easiest way in Bubble? It seems a bit overcomplicated.

Can you share the setup of your API Connector for this specific call?
Do you use the Call ‘As Data’ or ‘As Action’?
Or are you not using the API Connector at all and making the API call differently?

In the API Connector a GET request should be able to resolve objects with their individual keys that are stored in an Array…

1 Like

Hi @florianherzog
This is my call setup:

And this is my test output

This is where I’m stuck in the workflow:

Please note that in the workflow where I call this API, I do get the JSON output correctly.
However, it seems I can only fetch from the JSON output the list of items (“:each item” is the only selectable dynamic input, while I look for something like “current item”).
In other words, now I get output like [Hotel A, Hotel B, Hotel C] while I want to fetch only 1 hotel from the list instead per iteration.

The endgoal is to eventually feed ChatGPT with all hotel data from the API response, and ask for a good recommendation based on a prompt with specific hotel preferences.
Let me know if this explains.

It looks like this action is “Create a new Thing (Hotel)” which creates 1x Thing, hence why it only lets you specify “each hotel name”

If your API response (eg Hotels) is a list and you want to create multiple items… you should use “Schedule API workflow on a list”. Using this instead will enable you to iterate through each item in the array.

If you’ve not done this before, it may seem backwards because you have to create the backend workflow first and then schedule it.

Here’s a brief overview:

  1. Create a new backend workflow that accepts parameters for each field that you want to add
  2. On the action, select “create a new thing” and fill in the fields mapped to parameters
  3. Go back to your API call workflow where you are grabbing the Hotels
  4. Make your workflow “Schedule API on a List of things”… set it to run over the list from your API call and against the backend workflow you created in step 1
  5. Fill in the parameters that you want to pass in (eg Hotel name etc)
  6. Voila!
1 Like

So as I understand the process, you want to:

  1. GET Hotel list from API
  2. display result in a Repeating Group
  3. parallely pass the results to Chat GPT + a predefined (or user generated) prompt that asks for recommendations based on the user preferences
  4. (Perhaps Highlight the results in the repeating group that are advised by GPT)

For the displaying in the Repeating group:
Isn’t it possible to make custom states on the repeating group that are somewhat as follows:

  1. Hotelname → List of text
  2. price → list of numbers
  3. currency → list of text
  4. … → all other properties that you want to display per hotel

→ As soon as the GET has resolved, save all these values (each items’ value xyz) into the RG’s custom states (Result of step 7’s hotels: each item’s property name → Hotelname) (Res of 7’s hotels: each’s price) etc. etc.

Then make Data source of RG e.g. the hotelname and then within the cell of the repeating group, get the other data of the lists by RG’sprice:item # current cell’s index?

I did that like this with another API call and it worked fine.

How you then pass that to ChatGPT is another question that you’re probably more familiar with than I am :wink:

Like this you don’t have to save the hotel to your DB which imo would add unnecessary clout to your DB where its perhaps hard to ensure that you don’t have double entries and you do not have to write to disk, everytime a user makes a request. (or is there a unique identifier number provided by bookings?

In my case, I only create an instance of the Object that I’m querying from the API when the user add’s it to another Object within my database, so I don’t fill the DB with unnecessary data.

@florianherzog @rjwilkinson10
Thank you both for the feedback.

As I am not on the paid version yet since I’m still in QA, API scheduling is not available.
I will consider already starting a paid subscription for this, unless its possible to build with the free-version functionalities?

I kind of needed to shift my requirement as ChatGPT does not allow a lot of characters per prompt. So the idea now is to reform the response JSON to either one of below formats (just more concise than the original output) and use that variable for an API call to ChatGPT;

Format 1:
[
{
“name”: “Hotel A”,
“price”: 150,
“currency”: “USD”,
“reviewScore”: 8.5,
“checkin”: {
“from”: “14:00”,
“until”: “23:00”
}
},

Or Format 2 if format 1 is still really going to exceed max nr of characters:
[
[“Hotel A, 150 USD, 8.5”],
[“Hotel B, 200 USD, 9.0”]
]

Do you have an idea how to format the JSON to either one of these in the workflow? Is it still required to do API scheduling or is there other functionalities I can use? I have tried some JSON plugins but cant get it to work properly. :slight_smile:

I think with my solution, you dont need to schedule API workflows on a list, as you don’t have to create things for each return value of your GET call. You store all values client side in multiple custom states and proceed from there and only create an entry into your database, when your user proceeds with one option (this then is again possible with just one workflow). Does that make sense?

I’m trying to follow, but everything I tried in the workflow gave me the option “:each item”
I did manage to create a custom state earlier (i removed it from the flow as you can see in the screenshot), but if i display it in the tabel on frontend for testing purposes, it shows 1 row with column 1 [hotel a, hotel b, hotel c] and column 2 [price a, price b, price c]. I was unable to split the values in a RG.

What steps do I need to take here in the workflow to achieve what you mention, after step 7 in my screenshot?

I think we can skip displaying it in a RG for now, as I want to directly send the format I just mentioned to ChatGPT (This step I know how to do, just need to format the data in a concise way within Bubble workflow). The response from chatGPT should be displayed in the RG instead later on in the workflow.

This is the workflow, if I now select “Create a new thing” action, I can only select the lists of values.

t

As I understand your response you get from booking consits of n amount of Hotel, and each Hotel has values.

You need to store all values (:each item’s name, :each item’s price, …) in a seperate custom state which is a list of text. The order will be the same in each of these lists. Then you can reference in the RG (just make one for one Hotel Name) the item # current cells index and get the corresponding values from the other custom states.

And you can structure the JSON as request to GPT as follows:

Store API response as follows:

Hotel Names in as list of text (Custom State)

Price as a list of text (or number) (Custom State)

currency as a list of text (Custom State)

reviewScore as a list of text (or number) (Custom State)

checkin store as a list of text formatted like this-> formatting similar to below (Custom State)

{“from”: “14:00”, “until”, “23:00”}

then for the query to GPT (why do you btw need a JSON, can’t you just send a string as query with a HTTP GET (or POST?) request to GPT?:

[ hotelNames:format as text]

And then format each element as follows

{

“name”: “This hotelNames”,

“price”: price’s item# this hotelNames index,

“currency”: “currencies’ item# this hotelNames index”,

“reviewScore”: reviewScore’s item# this hotelNames index,

“checkin”: checkin’s item# this hotelNames index"

}

And like this you have a string that is properly formatted as JSON (you can also do the formatting differently to suit your Format style 2

Perhaps also add an index number, so that GPT can answer with a structured JSON like

“recommendations”: [{
“text”: “GPT recommends this hotel because it’s awsome”,
“index”: 1},
{
“text”: “GPT recommends this hotel because it’s even better”,
“index”: 2}
]
And then you can map the response values to the hotels again…

@florianherzog
" why do you btw need a JSON, can’t you just send a string as query with a HTTP GET (or POST?) request to GPT?"

I tried to sent the “Raw text” through API to GPT, but its results in an error. Not sure though if its because of the character limit or the JSON format with invalid characters upon transforming it to raw text. I first need to get rid of a lot of unnecessary data before GPT allows me to do the API call it looks like. Eventually sending the remainder as string would probably be fine.

I will try to go through your steps and see if I can make it work :slight_smile: .
Ill be back!

@florianherzog got it up working!
Was way easier to just take the JSON and;

  • format to text and build a more concise JSON there
  • add escaping
  • send that format back to GPT

Thanks a lot :smiley:

Very cool, happy it worked out for you
I wish you continued success in the build

1 Like

@florianherzog Next hickup, again an issue with data type conversion (quite a headache in bubble to be honest).

I receive a JSON code response from GPT, which would normally be instantly usable in Bubble.io workflow as custom state for RG. However, the GPT response is nested and hence this entire piece of JSON is considered a text again by bubble, rather than a list of texts that is usable for populating RGs.

JSON would be something like

Any idea if there’s some dynamic input action I can use in the workflow to convert it from text to list of texts, to be able to load this correctly in a RG?
I tried delimit by , and { but obviously that wont work as I then still cannot access the fields name, price etc individually.

This would be my incorrect table in that case:

almost there, thanks!!

Where did you receive the JSON from?
You can Initialize the API Call to GPT with the API Connector and then reference the individually retrieved values of the objects in the array… and use them as Data or Action

The JSON in my first screenshot from my prev. comment is inside of the “content” param in below response:

The data in the content param (which is the JSON ChatGPT sends to me since I ask for it to send it in JSON format), is considered text by bubble and hence i cannot load it into RGs.

Basically Im receiving a JSON within a JSON now

First: take time to get familiar with JSON structure. Nested JSON is not the same as JSON array. You have both stuff here. List is always an array and in JSON, an array is encoded between square brackets. Curly brackets are for objects.

Second, take time to search forum about chatgpt/open AI response. The content is often a string (that is delimited by doubles quotes… even if the content of this string is a JSON… this is not parsed by Bubble because in fact, the content is a string). There’s a lot of topics with solutions on the forum about this response type.

If I remember correctly from a program I’ve written, you should be able to define in the API call to OpenAI that the response should be a JSON, rather than a string within “[…]” quotes. But that’s nearly 7 months back and I made that in Python where your potentially much more flexible in what you http: request from the API…
So probably safest to go with Jici’s approach :wink:

… or you could string:find and replace:find and replace and replace “[” with “” and “]” with “” and then split by “,” which would give you the individual objects within the curly braces … but how you transform the string of into individual values per object easily is Client side is currently beyond my knowledge. I have the feeling, it shouldn’t be too hard with some smart text operations.

1 Like

Hi @florianherzog @Jici
I will try to figure this out. I just watched a manual on youtube but since it requires a backend workflow I will not be able yet to test, ,due to previewing backend workflows is on paid plans only.

I also tried the same through a JS plugin instead of backend workflow, but can’t seem to get it to work out either.