Best answer

How to modify the API response to consolidate child and childless keys


Userlevel 2
Badge +1

I am writing a custom zap to pull survey data from learning management system.  I got a lot of functionality working, but am stuck with how some of the data is being structured in the resultant JSON.  If the question is a multiple choice style question, the answer comes as a child record of user_answers key surrounded by curly brackets with a key pair nested beneath.  If it’s a free-text field, then the user_answers is being returned between square brackets.   Here’s an example JSON response of the two:

 

{

  "survey_id": "2071",

  "survey_name": "Course Survey",

  "user_id": "1",

  "user_name": "Bilbo B.",

  "completion_status": "Completed",

  "completed_on": "2023/01/09, 16:12:07",

  "completed_on_timestamp": "1673298727",

  "total_time": "39s",

  "total_time_seconds": 39,

  "questions": [

    {

      "id": "411",

      "text": "The course materials (slides, animations, ring of power, etc.) facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "406",

      "text": "What additional course topics would you like to see offered by Vestibular First?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        "I would like more courses on how to cook taters while in Mordor."

      ],

      "child_questions": []

    }

  ]

}

 

Ideally I would like them both to be returned it is with the multi-select answers with a key-pair nested beneath which should allow me to support both types of questions and answers with one field downstream.  

 

I think this needs to happen in the z.request(options) and before the return[results]; in the API Request, but I cannot find any good examples on how to handle this.  I appreciate any help this community can provide!

 

For reference, here is my current API Request which is generating the above JSON result.

 

 

const options = {

  url: `https://xxxx.hobbitlms.com/api/v1/getsurveyanswers/survey_id:${bundle.inputData.surveyID},user_id:${bundle.inputData.userID}`,

  method: 'GET',

  headers: {

    'Content-Type': 'application/json',

    'Accept': 'application/json'

  },

  params: {

  }

};

 

return z.request(options)

  .then((response) => {

    response.throwForStatus();

    const results = response.json;

    

    return[results];

  });

icon

Best answer by pesmonde 18 January 2023, 05:27

View original

This post has been closed for comments. Please create a new post if you need help or have a question about this topic.

21 replies

Userlevel 1
Badge +1

Hey @pesmonde!

Taking a look at your JSON object, you’ll need to access key-value questions
The data type associated with that key is an array or list (Depending on what language you’re using), what makes this more interesting that it’s actually a arrray/list of JSON/Dictionaries! 


The following are the assumptions I’m using to take place:

  • Each API request yield’s one user’s answers on one survey
  • The survey can have multiple questions, but does not need to iterate over the array/list object
  • The JSON object exists within the Zapier universe and does not get manipulated within custom code prior.
  • The JSON object is stored in a variable called json_object

In Python, JSON objects are similar to dictionary objects, where you need to provide a key value to the object to access the data.
Below is an explanation on how to access and iterate over the json_object. Please note that this is assuming that your json_object is saved to the variable. Otherwise an error will be thrown as json_object is undefined.

"""
Takes the length of the questions asked within the Course Survey ID
Range creates a list starting at 0 and ends at the length of the json_object, at an increment of 1
Iterates over the new list, in your example object it would be [0, 1]
Then it prints the objects to the terminal
"""


for i in range(len(json_object['questions'])):
print(json_object['questions'][i]['user_answers'])



"""
Output:
{'1': 'Strongly Agree'}
['I would like more courses on how to cook taters while in Mordor.']
"""

Now that we know how to access the data, let’s solve the issue at hand.

Ideally I would like them both to be returned it is with the multi-select answers with a key-pair nested beneath which should allow me to support both types of questions and answers with one field downstream.  


I’m a bit confused here, but will work with what I understand. It sounds like you’d like to have all the user_answers bundled together like such

[
{'1': 'Strongly Agree'},
['I would like more courses on how to cook taters while in Mordor.']
]

To achieve this, use the following python code:

r_list: list = []

for i in range(len(json_object['questions'])):
r_list.append(json_object['questions'][i]['user_answers'])


# In case you want to use this directly in Zapier's code functionality, we have to return the object
return r_list

 

I think this needs to happen in the z.request(options) and before the return[results]; in the API Request, but I cannot find any good examples on how to handle this.  I appreciate any help this community can provide!


You have the right idea about wanting to clean up the data prior to sending it to zapier. Ideally though, this should be handled outside of your API call. You’d want to do this as in the future you may need to access the full API data again. Doing such will lower your code’s cohesion


Let me know if this helps! If not we can hop on a quick call and discuss it 😁

Userlevel 6
Badge +8

Hey there,

Yes, the formatting of the response need to happen between these two lines

 

const results = response.json;



    

    return[results];

 

Can you, in this post, format that response the way you want it formatted? Then maybe we can come up with some code to get you from the original format to the desired format.

Userlevel 2
Badge +1

Thanks @CBorden and @shalgrim for your reply!  I appreciate your thorough response and I will clarify so it will make the most sense.   Here’s how I’d like to have the data returned--sorry for not doing this the first time.  I have highlighted the change I’d like to make to the response with a bolded white font on green background.

 

{

  "survey_id": "2071",

  "survey_name": "Course Survey",

  "user_id": "1",

  "user_name": "Bilbo B.",

  "completion_status": "Completed",

  "completed_on": "2023/01/09, 16:12:07",

  "completed_on_timestamp": "1673298727",

  "total_time": "39s",

  "total_time_seconds": 39,

  "questions": [

    {

      "id": "411",

      "text": "The course materials (slides, animations, ring of power, etc.) facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "406",

      "text": "What additional course topics would you like to see offered by Vestibular First?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "I would like more courses on how to cook taters while in Mordor."

      },

      "child_questions": []

    }

  ]

}

Userlevel 1
Badge +1

Hey @pesmonde,

Thank for the clarification! My original answer isn’t the solution. Not to worry, it takes iterations to get to the right answer 😉

However it’s similar to what the solution would be.

Before I dive into that, there’s another question that would need to be answered, and this could only be achieved through the API documentation for the LMS. Which after looking through, doesn’t give insight I’m presuming that it should be okay. Here’s an explanation of what I meant though.

Since the user answer for the free text is being returned as a list, I’m curious to what causes another string to be appended to the list.

So from the original:

...
"type": "Free text",
"answers": [],
"user_answers": [
"I would like more courses on how to cook taters while in Mordor."
],
...

to something like this:

...
"type": "Free text",
"answers": [],
"user_answers": [
"I would like more courses on how to cook taters while in Mordor.",
"There should be a section for picky eaters like Gandolf"
],
...


I’ll provide a complete solution in python for ease of use:

import requests
from typing import DefaultDict

# Temporary Data Structure
# Default dicts won't throw an error if a key-value isn't present prior to calling the key.
tmp_user_answer = DefaultDict()

# URL
'''
f-strings: A cleaner way to introduce variables into strings. To use wrap your string with a single or double quote.
When you want to use introduce a variable wrap the variable with curly brackets.
Example:
foo = 'bar'
print(f'My variable name is: {foo}
Output: My variable name is: bar
'''

url: str = f'https://xxxx.hobbitlms.com/api/v1/getsurveyanswers/survey_id:{bundle.inputData.surveyID},user_id:{bundle.inputData.userID}`

# Headers
headers: dict = {'Content-Type': 'application/json',
'Accept': 'application/json'}

# Send the request
response = requests.get(url=url, headers=headers)

# Raise the non-200 status code
response.raise_for_status()

# Transform the data to the requested structure
# Iterate over the number of questions returned
for i in range(len(json_object['questions'])):
# Skip all questions that are not of type "Free text"
if json_object['questions'][i]['type'] != 'Free text':
continue
# Iterate over the list/array object of user_answers for questions of type "Free text"
for j in range(len(json_object['questions'][i]['user_answers'])):
# Use the default dictionary to hold the index and the string from the list/array
tmp_user_answer[j+1] = json_object['questions'][i]['user_answers'][j]

# Replace the list/array with the new structure.
json_object['questions'][i]['user_answers'] = tmp_user_answer



return json_object

This will return the object structured where the user_answers for Free text are in a dictionary, or wrapped in curly brackets, “{ }”.

PLEASE NOTE: I attempted to make sure that regardless of the size of the string in the array and the size of the actual array everything will be handled. I checked the API documentation but couldn’t find guidance on what makes the array have different sizes.

All that you would need to do is update the URL, hope this is what you’re looking for!

PS: If there’s any questions about what I did or how I did it, please let me know. I’m more than happy to break things down 😁

Cheers to automating!

 

EDIT:
This was created outside of the Zapier universe and with a dummy URL. Please let me know if there’s any kind of errors, please include screenshots as well :D

EDIT 2:
Added an explanation into default dictionary and f-strings for python

Userlevel 1
Badge +1

Can't edit my message above. However tested to request code with a test url and works perfectly ✌️

 

The code should get you to where you need to go

Userlevel 2
Badge +1

Hi @CBorden --thanks for your very thorough response!  I will give this a try, however, one thing I’m not sure of is that the code mode of the Zap builder lets you use Python.  Here’s what I found on their developer FAQ:

 

If your API calls need more customization, however, or your API response is in a non-JSON format, you will need to write custom JavaScript code to handle your API call and/or response parsing. The Zapier visual builder includes a Switch to Code Mode toggle on every API request, similar to the one pictured above, that switches that specific API call to code mode.

 

 

It does look similar, but it would need to be within this part of the API Request section:

 

 

return z.request(options)

  .then((response) => {

    response.throwForStatus();

    const results = response.json;

    

    return[results];

  });

 

My understanding is that it would transform the information received back from the API response and before the return[results]; line.  It seems like your code will do the trick if it’s able to input what’s coming back and then apply the transforms you’ve coded.  

 

I hope this makes sense and thanks again for taking a look.

Userlevel 1
Badge +1

Hey @pesmonde -- No problem!
After diving in a bit deeper I’ve been answering the question wrong. I was under the presumption that this was occurring within a zap, and not building out a handler for a Zapier Module. My apologies.

I’m not as strongly suited in Javascript, however this is what I came up with:

// object to store modified user_answers
let tmp_user_answer = {};

// To keep the indexing of the object congruent with the request, start i at 1.
// If the requested indexing should be at 0, change the initial i variable to 0 below
for (var i = 0, _json_length = results["questions"].length; i < _json_length; i += 1) {
// Check if the type of question the user answered is Free text, if not, continue to the next question within the survey
if (results["questions"][i]["type"] !== "Free text") {continue;}

// Iterate over each user answer if the question type is Free text
for (var j = 0, _user_answers_len = results["questions"][i]["user_answers"].length; j < _user_answers_len; j += 1) {
// Create a new object with a key-value of the index of j, offset by 1. To get this to index at 0, remove the +1 below
tmp_user_answer[j + 1] = results["questions"][i]["user_answers"][j];
}
// Replace the list/array with the new object.
results["questions"][i]["user_answers"] = tmp_user_answer;
}

Apologies for bringing us around the ringer, but now incase you ever need a webhooks handler in python, you got one!

This gives the same exact result that was manipulated in python.

Let me know if this get’s you in a better direction!

Cheers

Userlevel 2
Badge +1

Thanks @CBorden!  This is exactly what I was looking for--sorry it took so long to get to this point.  I sincerely appreciate all of your explanations and how you stepped through the problems.  I definitely learned a lot from your post--thank you so much!

Userlevel 1
Badge +1

No problem @pesmonde! -- I should of led with more questions rather than more information.
I couldn’t of gotten to the solution without you! Appreciate you listening to the explanations and letting me go off on the soapbox

I am more happy to break down everything into byte sized bits. (I’ll see myself out for that programmer pun)

Userlevel 2
Badge +1

Hi @CBorden -- I spoke too soon!  We are very close though.   Here’s the response below.  The only issue is that the free-text answers are all the same. I did a test survey and typed a unique response to each answer, but it looks like it’s just taking the last question’s user_answer and putting it for all those questions.  See the highlighted area below:

 

{

  "survey_id": "2071",

  "survey_name": "Course Survey",

  "user_id": "1",

  "user_name": "P. Esmonde",

  "completion_status": "Completed",

  "completed_on": "2023/01/17, 10:00:59",

  "completed_on_timestamp": "1673967659",

  "total_time": "1m 51s",

  "total_time_seconds": 111,

  "questions": [

    {

      "id": "411",

      "text": "The course materials (slides, animations, videos, etc.) facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "410",

      "text": "The instructors presented in a manner that facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "404",

      "text": "How likely are you to recommend this course to another clinician, researcher, or student?",

      "type": "Multiple choice",

      "answers": {

        "1": "10 - Very Likely",

        "2": "9",

        "3": "8",

        "4": "7",

        "5": "6",

        "6": "5",

        "7": "4",

        "8": "3",

        "9": "2",

        "10": "1",

        "11": "0 - Not Likely"

      },

      "user_answers": {

        "1": "10 - Very Likely"

      },

      "child_questions": []

    },

    {

      "id": "405",

      "text": "Please let us know why or why not you would recommend us to a clinician, researcher, or student:",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    },

    {

      "id": "402",

      "text": "What did you like best about this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    },

    {

      "id": "403",

      "text": "What would you improve for this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    },

    {

      "id": "412",

      "text": "What is something helpful you learned from this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    },

    {

      "id": "406",

      "text": "What additional course topics would you like to see offered by Vestibular First?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    }

  ]

}

Userlevel 1
Badge +1

Sorry about that @pesmonde!

Bugga! Looks like its caused from how I’m handling the data within the loop. Thanks for giving this a test run for me!

Here’s the updated code:

// object to store modified user_answers
let tmp_user_answer = {};

// To keep the indexing of the object congruent with the request, start i at 1.
// If the requested indexing should be at 0, change the initial i variable to 0 below
for (var i = 0, _json_length = results["questions"].length; i < _json_length; i++) {
// Check if the type of question the user answered is Free text, if not, continue to the next question within the survey
if (results["questions"][i]["type"] !== "Free text") {continue;}

// Iterate over each user answer if the question type is Free text
for (var j = 0, _user_answers_len = results["questions"][i]["user_answers"].length; j < _user_answers_len; j++) {
// Create a new object with a key-value of the index of j, offset by 1. To get this to index at 0, remove the +1 below
tmp_user_answer[j+1] = results["questions"][i]["user_answers"][j];
// Replace the list/array with the new object.
results["questions"][i]["user_answers"][j] = tmp_user_answer[j+1];
}
}

It should still be dynamic to handle all questions and lines within user_answers.

Let me know if this is works!

Userlevel 2
Badge +1

Hi @CBorden,

 

Thanks for your revision.  The answers are now in the right spot, but they’re not being correctly nested with a key pair.  See the highlighted areas below. 

 

{

  "survey_id": "2071",

  "survey_name": "Course Survey",

  "user_id": "1",

  "user_name": "P. Esmonde",

  "completion_status": "Completed",

  "completed_on": "2023/01/17, 10:00:59",

  "completed_on_timestamp": "1673967659",

  "total_time": "1m 51s",

  "total_time_seconds": 111,

  "questions": [

    {

      "id": "411",

      "text": "The course materials (slides, animations, videos, etc.) facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "410",

      "text": "The instructors presented in a manner that facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "404",

      "text": "How likely are you to recommend this course to another clinician, researcher, or student?",

      "type": "Multiple choice",

      "answers": {

        "1": "10 - Very Likely",

        "2": "9",

        "3": "8",

        "4": "7",

        "5": "6",

        "6": "5",

        "7": "4",

        "8": "3",

        "9": "2",

        "10": "1",

        "11": "0 - Not Likely"

      },

      "user_answers": {

        "1": "10 - Very Likely"

      },

      "child_questions": []

    },

    {

      "id": "405",

      "text": "Please let us know why or why not you would recommend us to a clinician, researcher, or student:",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        "NPS description"

      ],

      "child_questions": []

    },

    {

      "id": "402",

      "text": "What did you like best about this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        "i liked everything the best"

      ],

      "child_questions": []

    },

    {

      "id": "403",

      "text": "What would you improve for this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        "i would improve nothing"

      ],

      "child_questions": []

    },

    {

      "id": "412",

      "text": "What is something helpful you learned from this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        "so many things were helpful!"

      ],

      "child_questions": []

    },

    {

      "id": "406",

      "text": "What additional course topics would you like to see offered by Vestibular First?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        "additional course topics are not necessary"

      ],

      "child_questions": []

    }

  ]

}

Userlevel 1
Badge +1

My fault.

I’m assigning the value of the tmp_user_answer dictionary to the JSON response object, instead of nesting the object itself.

We’re in this together!

// object to store modified user_answers
let tmp_user_answer = {};

// To keep the indexing of the object congruent with the request, start i at 1.
// If the requested indexing should be at 0, change the initial i variable to 0 below
for (var i = 0, _json_length = results["questions"].length; i < _json_length; i++) {
// Check if the type of question the user answered is Free text, if not, continue to the next question within the survey
if (results["questions"][i]["type"] !== "Free text") {continue;}

// Iterate over each user answer if the question type is Free text
for (var j = 0, _user_answers_len = results["questions"][i]["user_answers"].length; j < _user_answers_len; j++) {
// Create a new object with a key-value of the index of j, offset by 1. To get this to index at 0, remove the +1 below
tmp_user_answer[j+1] = results["questions"][i]["user_answers"][j];
// Replace the list/array with the new object.
results["questions"][i]["user_answers"][j] = tmp_user_answer;
}
}

That last line, I remove the Object Key (which was wrapped in the square brackets) this now assigns the results object user_answers, with the key-value pair.

I’m skeptical tbh, on the online editor I’m using this was an example output for the code.

As you can see, it appears to be a nested object with a key of 0, and a value of another dictionary

Nonetheless, here’s to another iteration!

Userlevel 2
Badge +1

Hi @CBorden ,

 

I am seeing the same as you with respect to the output.  Take a look at the output with the last iteration.  The same answer in each user_answer is happening again, and you’re right that there is an extra pair of square brackets.  Here’s the output:

 

{

  "survey_id": "2071",

  "survey_name": "Course Survey",

  "user_id": "1",

  "user_name": "P. Esmonde",

  "completion_status": "Completed",

  "completed_on": "2023/01/17, 10:00:59",

  "completed_on_timestamp": "1673967659",

  "total_time": "1m 51s",

  "total_time_seconds": 111,

  "questions": [

    {

      "id": "411",

      "text": "The course materials (slides, animations, videos, etc.) facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "410",

      "text": "The instructors presented in a manner that facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "404",

      "text": "How likely are you to recommend this course to another clinician, researcher, or student?",

      "type": "Multiple choice",

      "answers": {

        "1": "10 - Very Likely",

        "2": "9",

        "3": "8",

        "4": "7",

        "5": "6",

        "6": "5",

        "7": "4",

        "8": "3",

        "9": "2",

        "10": "1",

        "11": "0 - Not Likely"

      },

      "user_answers": {

        "1": "10 - Very Likely"

      },

      "child_questions": []

    },

    {

      "id": "405",

      "text": "Please let us know why or why not you would recommend us to a clinician, researcher, or student:",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        {

          "1": "additional course topics are not necessary"

        }

      ],

      "child_questions": []

    },

    {

      "id": "402",

      "text": "What did you like best about this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        {

          "1": "additional course topics are not necessary"

        }

      ],

      "child_questions": []

    },

    {

      "id": "403",

      "text": "What would you improve for this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        {

          "1": "additional course topics are not necessary"

        }

      ],

      "child_questions": []

    },

    {

      "id": "412",

      "text": "What is something helpful you learned from this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        {

          "1": "additional course topics are not necessary"

        }

      ],

      "child_questions": []

    },

    {

      "id": "406",

      "text": "What additional course topics would you like to see offered by Vestibular First?",

      "type": "Free text",

      "answers": [],

      "user_answers": [

        {

          "1": "additional course topics are not necessary"

        }

      ],

      "child_questions": []

    }

  ]

}

Userlevel 1
Badge +1

 Man, javascript is picky, I was changing the variable type in the last line..
This should take care of it 😂

// object to store modified user_answers
let tmp_user_answer = {};

// To keep the indexing of the object congruent with the request, start i at 1.
// If the requested indexing should be at 0, change the initial i variable to 0 below
for (var i = 0, _json_length = results["questions"].length; i < _json_length; i++) {
// Check if the type of question the user answered is Free text, if not, continue to the next question within the survey
if (results["questions"][i]["type"] !== "Free text") {continue;}

// Iterate over each user answer if the question type is Free text
for (var j = 0, _user_answers_len = results["questions"][i]["user_answers"].length; j < _user_answers_len; j++) {
// Create a new object with a key-value of the index of j, offset by 1. To get this to index at 0, remove the +1 below
tmp_user_answer[j+1] = results["questions"][i]["user_answers"][j];
// Replace the list/array with the new object.
results["questions"][i]["user_answers"] = tmp_user_answer;
}
}

 

Userlevel 2
Badge +1

Hi @CBorden ,

 

Looks like it’s putting the same values back into the user_answers.  I will post below, but at this point, I don’t want to overstay my welcome with your help, so I am going to reach out to one of the zapier consultants on this site.  It looks like a very simple replacement, but obviously that’s not the case and I’m sorry that you have put so much effort into this without the result you wanted.  I did post this into the openai engine and it’s recommending to use the .reduce function to convert it, but I am even more unfamiliar with that.  Thanks again for your help.

 

{

  "survey_id": "2071",

  "survey_name": "Course Survey",

  "user_id": "1",

  "user_name": "P. Esmonde",

  "completion_status": "Completed",

  "completed_on": "2023/01/17, 10:00:59",

  "completed_on_timestamp": "1673967659",

  "total_time": "1m 51s",

  "total_time_seconds": 111,

  "questions": [

    {

      "id": "411",

      "text": "The course materials (slides, animations, videos, etc.) facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "410",

      "text": "The instructors presented in a manner that facilitated my learning.",

      "type": "Multiple choice",

      "answers": {

        "1": "Strongly Agree",

        "2": "Agree",

        "3": "Neither Agree or Disagree",

        "4": "Disagree",

        "5": "Strongly Disagree"

      },

      "user_answers": {

        "1": "Strongly Agree"

      },

      "child_questions": []

    },

    {

      "id": "404",

      "text": "How likely are you to recommend this course to another clinician, researcher, or student?",

      "type": "Multiple choice",

      "answers": {

        "1": "10 - Very Likely",

        "2": "9",

        "3": "8",

        "4": "7",

        "5": "6",

        "6": "5",

        "7": "4",

        "8": "3",

        "9": "2",

        "10": "1",

        "11": "0 - Not Likely"

      },

      "user_answers": {

        "1": "10 - Very Likely"

      },

      "child_questions": []

    },

    {

      "id": "405",

      "text": "Please let us know why or why not you would recommend us to a clinician, researcher, or student:",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    },

    {

      "id": "402",

      "text": "What did you like best about this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    },

    {

      "id": "403",

      "text": "What would you improve for this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    },

    {

      "id": "412",

      "text": "What is something helpful you learned from this course?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    },

    {

      "id": "406",

      "text": "What additional course topics would you like to see offered by Vestibular First?",

      "type": "Free text",

      "answers": [],

      "user_answers": {

        "1": "additional course topics are not necessary"

      },

      "child_questions": []

    }

  ]

}

Userlevel 1
Badge +1

hey @pesmonde 

Not to worry! I enjoyed the challenge (Though it probably shouldn’t of been as large of one as it was.) This was actually my first crack at Javascript and by no means an expert.

Sorry for giving false hope that we were right on the cusp of solving the issue :(

Perhaps OpenAI could translate the python code into the Javascript code as an alternative

Userlevel 2
Badge +1

Hi @CBorden,

 

So I figured, what the heck--give it a try--and it did convert the code over from python to javascript:

 

 

let tmp_user_answer = {};   

let json_object = results;

    

for (let i = 0; i < json_object["questions"].length; i++) {

if (json_object["questions"][i]["type"] !== "Free text") {continue;}

for (let j = 0; j < json_object["questions"][i]["user_answers"].length; j++) {

  tmp_user_answer[j + 1] = json_object["questions"][i]["user_answers"][j];

}

json_object["questions"][i]["user_answers"] = tmp_user_answer;

}

 

It is having the same issue as before, however, wherein the answers are all the same.  It is, however, nested correctly.  I have attached the current vs desired API response to make it easier for you to check your script.

Userlevel 2
Badge +1

Hi @shalgrim and @CBorden ,

 

I am kinda surprised this worked, but I’m amazed that I was able to get the OpenAI chat engine to write the below code that worked perfectly.  I fed it two truncated JSON strings with just one multi-select and one free-text answer with one being the current and the second being my ideal outcome.  It did the rest and I’m kinda blown away.  Here’s the code it came up with:

 

return z.request(options)

  .then((response) => {

    response.throwForStatus();

    const results = response.json;


results.questions.forEach(question => {

  if (question.type === 'Free text') {

    question.user_answers = { "1": question.user_answers[0] };

  }

});

return[results];

 

Here’s exactly what I typed into the chat.openai.com window:

 

Convert this JSON

{
"survey_id": "2071",
"survey_name": "Course Survey",
"user_id": "1",
"user_name": "P. Esmonde",
"completion_status": "Completed",
"completed_on": "2023/01/17, 10:00:59",
"completed_on_timestamp": "1673967659",
"total_time": "1m 51s",
"total_time_seconds": 111,
"questions": [
{
"id": "411",
"text": "The course materials (slides, animations, videos, etc.) facilitated my learning.",
"type": "Multiple choice",
"answers": {
"1": "Strongly Agree",
"2": "Agree",
"3": "Neither Agree or Disagree",
"4": "Disagree",
"5": "Strongly Disagree"
},
"user_answers": {
"1": "Strongly Agree"
},
"child_questions": []
},
{
"id": "412",
"text": "What is something helpful you learned from this course?",
"type": "Free text",
"answers": [],
"user_answers": [
"so many things were helpful!"
],
"child_questions": []
},
{
"id": "406",
"text": "What additional course topics would you like to see offered by Vestibular First?",
"type": "Free text",
"answers": [],
"user_answers": [
"additional course topics are not necessary"
],
"child_questions": []
}
]
}

to this JSON

{
"survey_id": "2071",
"survey_name": "Course Survey",
"user_id": "1",
"user_name": "P. Esmonde",
"completion_status": "Completed",
"completed_on": "2023/01/17, 10:00:59",
"completed_on_timestamp": "1673967659",
"total_time": "1m 51s",
"total_time_seconds": 111,
"questions": [
{
"id": "411",
"text": "The course materials (slides, animations, videos, etc.) facilitated my learning.",
"type": "Multiple choice",
"answers": {
"1": "Strongly Agree",
"2": "Agree",
"3": "Neither Agree or Disagree",
"4": "Disagree",
"5": "Strongly Disagree"
},
"user_answers": {
"1": "Strongly Agree"
},
"child_questions": []
},
{
"id": "412",
"text": "What is something helpful you learned from this course?",
"type": "Free text",
"answers": [],
"user_answers": {
"1": "so many things were helpful!"
},
"child_questions": []
},
{
"id": "406",
"text": "What additional course topics would you like to see offered by Vestibular First?",
"type": "Free text",
"answers": [],
"user_answers": {
"1": "additional course topics are not necessary"
},
"child_questions": []
}
]
}

with javascript

 

This is what is supplied me which I adapted to the zapier interface:

 

 

Userlevel 6
Badge +8

Amazing

Userlevel 1
Badge +1

Thanks for showing the output and the steps you took!
I knew there was a better way to handle JSON in Javascript (Being that JS in JSON stands for Java Script) 😂😂