提问人:Hack-R 提问时间:8/31/2023 更新时间:10/23/2023 访问量:45
Google 表单的 JSON 数据是否缺少部分的项目 ID(这是提取跳过逻辑所必需的)?
Are Google Forms' JSON data missing Item Id's for sections (which is necessary for extracting skip logic)?
问:
Google 表单的数据可以通过 API 提取。使用 Python,我是这样拉的:
from __future__ import print_function
from apiclient import discovery
from httplib2 import Http
from oauth2client.service_account import ServiceAccountCredentials
import json
SCOPES = "https://www.googleapis.com/auth/forms.body.readonly"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"
def get_google_form_data(form_id):
creds = ServiceAccountCredentials.from_json_keyfile_name('service.json', SCOPES)
http_auth = creds.authorize(Http())
service = discovery.build('forms', 'v1', http=http_auth, discoveryServiceUrl=DISCOVERY_DOC, static_discovery=False)
result = service.forms().get(formId=form_id).execute()
return result
if __name__ == "__main__":
form_id = 'xxx'
json_data = get_google_form_data(form_id)
with open("form_data.json", "w") as f:
json.dump(json_data, f, indent=4)
测验的受访者可能会看到不同的问题,具体取决于他们的答案。在表单所有者的表单 Web 视图中,这些不同的部分被连续标记(“第 1 部分”、“第 2 部分”等),并且它们可以使用这些部分标签将值(也称为答案)与“跳过逻辑”相关联。例如,第一个答案可能链接到第 10 节,第二个答案选项可能链接到第 20 节。
在 JSON 数据中,它不是那些连续的用户友好标签,而是调用它,即“要转到的部分标题的项目 ID”。这将是简单明了的,但是 API(我可以找到)中没有任何内容可用于查找识别标题中的相应部分标题或问题。它具有“questionID”,它也是一个项目 ID,但这些 ID 与部分 ID 不同。goToSectionId
我认为我一定犯了一个错误,但是如果我使用任何值搜索原始 JSON,在每种情况下它们都只出现一次,因此它们不提供映射。如何提取跳过逻辑?goToSectionId
以下是 API 文档: https://developers.google.com/forms/api/reference/rest/v1/forms#QuestionItem
答:
我遇到了一个非常相似的问题,我的意思是将条件逻辑归因于 ChoiceQuestion 类型。但是,在用 Java 开发了我的项目后,我发现的解决方案是不同的,所以尽管代码可能对您没有用,但请提取“概念”。
让我们从理论开始:我们需要创建一个格式正确的 JSON 请求来创建一个表单。在此 JSON 请求中,我们可以将选择的 itemId 属性分配给 Items,而不是满足于它们的自动归因。
即:
{
"formId": null,
"info":{
"documentTitle":"Test1",
"title":"Test 1"
},
"items":[{
"itemId":"00000001",
"questionItem": {
"question":{
"choiceQuestion":{
"options":[{
"value":"Option 1",
"goToSectionId": "00000002"
},
{
"value":"Option 2",
"goToSectionId": "00000004"
}],
"type":"DROP_DOWN"
},
"questionId":"619ff865"}
},
"title":"Question 1"
},
{
"description":"New Page descriptor",
"itemId":"00000002",
"pageBreakItem":{},
"title":"ciao"
},
{
"itemId":"00000003",
"questionItem":{
"question":{
"choiceQuestion":{
"options":[{
"value":"Yes"
},
{
"value":"No"
}],
"type":"RADIO"
},
"questionId":"73bcb98f"
}},
"title":"Question 2"
},
{
"itemId":"00000004",
"pageBreakItem":{
},
"title":"New Page descriptor"
},
{
"itemId":"00000005",
"questionItem":{
"question":{
"choiceQuestion":{
"options":[{
"value":"Yes"
},
{
"value":"No"
}],
"type":"RADIO"
},
"questionId":"73bcb98f"
}},
"title":"Question 3"
},],
"responderUri": null,
"revisionId": null
}
请注意,上面的 JSON 包含三个问题和两个分页符。问题 1 的答案将激活跳过问题 2(第 00000003 项)或问题 3(第 00000005 项)的逻辑。
请注意,pageBreakItems 对应于问题 1 中的选项。
就我而言,这是困难的部分。注意到 Google 表单 API 和相关的 Java 库使用 BatchRequest,其中每个元素都是按顺序插入的,插入问题会返回错误,因为选项的 ID 与后续的 pageBreakitems(尚未插入)之间没有对应关系。
就我而言,解决方案是提出 2 个不同的请求:
第一个插入所有元素和 PageBreakItems,但带有条件逻辑的问题除外 (Question1)
第二个插入带有条件逻辑的问题,如问题 1
例如,我附上我编写的 Java 方法:
private void publishForm(Form form, CustomForm customForm) throws IOException {
BatchUpdateFormRequest batchRequest = new BatchUpdateFormRequest();
List<Request> requests = new ArrayList<>();
List<Request> goToSectionIdTypeRequest = new ArrayList<>();
Integer counter = 0;
for(CustomItem item : customForm.getItems()){
Request request = new Request();
request.setCreateItem(new CreateItemRequest());
request.getCreateItem().setLocation(new Location());
request.getCreateItem().setItem(item.getItem());
request.getCreateItem().getLocation().setIndex(counter);
/*
* If the element is a dropdown it can have also an goToSectionId parameter:
* in this case, it must be pushed inside the form in a second time
*/
if (item.getQuestionItem() != null) {
if (item.getQuestionItem().getQuestion().getChoiceQuestion() != null) {
if (item.getQuestionItem().getQuestion().getChoiceQuestion().getType() != null) {
String choiceType = item.getQuestionItem().getQuestion().getChoiceQuestion().getType();
if (choiceType.equals(ChoiceType.DROPDOWN.label)) {
if (item.getQuestionItem().getQuestion().getChoiceQuestion().getOptions().get(1).getGoToSectionId() != null) {
goToSectionIdTypeRequest.add(request);
continue;
}
}
}
}
}
requests.add(request);
counter++;
}
batchRequest.setRequests(requests);
this.formservice.forms().batchUpdate(form.getFormId(), batchRequest).setAccessToken(token).execute();
batchRequest.setRequests(goToSectionIdTypeRequest);
this.formservice.forms().batchUpdate(form.getFormId(), batchRequest).setAccessToken(token).execute();
它并不优雅,但它有效。
我仍然随时为您服务,希望您能解决您的问题。
谢谢。
评论