cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
MichaelFerero
Community Member

Quiz question creation via curl/JSON error

I'm using curl to send create quiz questions to an already create quiz, the JSON is as follows:

{ "question": {
"question_name": "Question 3",
"question_text": "Two of the basic instructions implemented by a programming language include:",
"question_type": "multiple_choice_question",
"points_possible": 2,
"answers": [
{
"answer_html": "input and resource allocation",
"answer_weight": 0
},
{
"answer_html": "math and string processing",
"answer_weight": 0
},
{
"answer_html": "output and monitoring program execution",
"answer_weight": 0
},
{
"answer_html": "conditional execution and repetition",
"answer_weight": 100
}
]
}
}

When I attempt to upload it using this curl command:

curl 'https://vccs.instructure.com/api/v1/courses/22246/quizzes/3106210/questions' \
--trace q.output \
-X POST \
-d @q3.json \
-H "Content-type: application/json" \
-H "Authorization: Bearer $CANVAS_TOKEN" > q1.html

I get the following error:

{"errors":[{"message":"An error occurred.","error_code":"internal_server_error"}],"error_report_id":6575670}

Now, if I remove the "answers" piece, it works . . . but I can't see anything wrong with it.  I've looked for UTF-8 characters . . . tabs  . . . nothing there

It is very possible I've stared at this for so long I can't see the issue.

 

Labels (1)
Tags (4)
0 Kudos
4 Replies
James
Community Champion

@MichaelFerero 

The structure of the Answers object is a bit ambiguous. It is an array of answers, but it needs the index in there and just sending the JSON object doesn't do that for you.

One way to get the keys is to create an object and use the index as the property name.

{
  "question": {
    "question_name": "Question 3",
    "question_text": "Two of the basic instructions implemented by a programming language include:",
    "question_type": "multiple_choice_question",
    "points_possible": 2,
    "answers": {
      "0": {
        "answer_text": "input and resource allocation",
        "answer_weight": 0
      },
      "1": {
        "answer_text": "math and string processing",
        "answer_weight": 0
      },
      "2": {
        "answer_text": "output and monitoring program execution",
        "answer_weight": 0
      },
      "3": {
        "answer_text": "conditional execution and repetition",
        "answer_weight": 100
      }
    }
  }
}

 

I used answer_text instead of answer_html because there was no html in your text. If you're sending answer_html, you should wrap your text in HTML elements. By default, Canvas uses <p>...</p>

To figure out information like this, I use the developer tools in Chrome and look at the network traffic that is sent when I perform the action within Canvas. Then I know what the format should look like. What I saw was stuff like this:

questions[answers][0][answer_text]
questions[answers][0][answer_weight]

There was a bunch more, but that let me know what it should look like and the rest of the junk was junk -- it was for other types of questions.

James,

Thank you for the post. That worked. It's not to the JSON standard, but it works. Is there no place where this is documented other than looking at the network traffic? I can't be the only one trying or having done this . . .

Not moaning at you . . . just wondering why it is so hard to find solid documentation. We programmers do live by that . . .

James
Community Champion

@MichaelFerero 

I suppose if one knew how to read Ruby, one could look at the source code for Canvas and potentially figure it out. I don't (know Ruby) so I find it easier to watch network traffic and reverse engineer. Getting Canvas to document that is unlikely, they're in the process of deprecating classic quizzes for new quizzes (which doesn't have a public API at all yet).

When you look at it from a application/x-www-url-encoded form perspective, it makes sense why it's done that way. It's an array of answers where each answer is an object. It needs someway to distinguish answer_text for response 0 from answer_text for response 1. You don't get that sense from the documentation.

The other gotcha is sending array data that are strings. If I'm doing an include which is an array of strings in the querystring of the URL (GET or PUT), then I have to include the [] to tell it that it is an array, but I don't put in the index:  include[]=user&include[]=submission_history. If you don't put in the brackets to tell it that it's multi-value, then it will only keep one of them.

Maybe this one is different because it's an array of objects as opposed to an array of strings?

Trying answers[] in your JSON was the first thing I tried and it accepted it, but it didn't recognize any of the answers.  I had to dig into some code that I had, but didn't look at it close enough to see that I was adding the key, so I resorted to the network sniffing.

Anyway, the Quiz Submission Questions documentation has an Appendix after the methods of the Question Answer Formats that contains more information, but not anything that would tell you that just putting in an array of objects wouldn't work. It has to do with the submission rather than the creation.

jackyjoy123
Community Member

thanks for the awesome information.