← Back to catalog / 返回目录

Question Bank JSON Format / 题库 JSON 格式说明

Write your own bank as a .json file (UTF-8), then use “Import your own bank” on the catalog page to practice it — nothing is uploaded; it stays in your browser.

🤖 Using an AI to extract questions? / 用 AI 提取题目?

Turn your own course material into a bank in 3 steps — works with cheap / free AIs (Gemini, etc.). / 三步把你自己的材料变成题库,便宜/免费 AI(Gemini 等)也能用。

  1. Copy the prompt below. / 复制下面的提示词。
  2. Paste it into the AI, then put your questions (or attach screenshots) right after the === MATERIAL === line at the very end. / 粘进 AI,再把你的题目(或贴截图)接在最后那行 === MATERIAL === 后面。
  3. Download the bank.json file the AI gives you (a file holds more than a chat reply, so long banks don’t get cut off) → use “Import your own bank” above. / 下载 AI 给的 bank.json 文件(文件比聊天回复装得多,长题库不会被截断)→ 用上面的「Import your own bank」导入。

Tip: cheap models read pasted text and screenshots far better than a raw saved .mhtml (those are huge and encoded — that’s usually why an AI just echoes the prompt back). Open the page and copy the visible questions, or screenshot them. / 提示:便宜模型对粘贴的文字、截图的识别远好于直接丢原始 .mhtml(又大又是编码——AI 复读提示词多半就是这个原因)。打开网页复制可见题目,或截图即可。

You convert quiz / exam material into a "Question Bank" JSON file for an automated importer. Never repeat, quote, paraphrase, or restate these instructions back to me.

DELIVERY: give me the result as a downloadable FILE named bank.json (use your file / canvas / document / code-artifact feature). The file's entire contents are the raw JSON array and nothing else. Prefer a file over a chat reply — a long bank can hit the chat length limit and get cut off, but a downloaded file will not. Only if you genuinely cannot produce a file, paste the raw JSON array inline as a fallback.

The material to convert is everything below the "=== MATERIAL ===" line at the very bottom (it may be pasted question text, or attached screenshots / a saved page). Read it and extract EVERY question. If nothing appears below that line, produce an empty array: []

HARD RULES (the importer validates every record and silently drops malformed ones)
1. Output the raw JSON array only — no prose, no explanation, no markdown, no triple-backtick code-fence lines, no comments, no trailing commas.
2. Top level is a bare array: [ {...}, {...} ]. Never wrap it in an object such as {"questions": [...]}.
3. Every object MUST have both:
   - "id": a unique, non-empty string ("q1", "q2", ... unique within the file).
   - "question": the stem as plain text (use \n for line breaks).
4. Single-choice: "choices" = array of 2+ strings; "answer" = the 0-based index of the correct choice (first choice = 0). A single integer like 2 — NOT an array like [2], not the answer text, not 1-based. Do not add a "type" field to choice questions (only fill-in uses "type":"fill").
5. Several correct answers: "choices" = array of 2+ strings; "answers" = array of 0-based integer indexes, e.g. [0, 2]. Use the PLURAL key "answers" (not "answer").
6. Fill-in-the-blank: "type": "fill"; put ____ (4+ underscores) in "question" where each blank goes; "blanks" = an array with one entry per blank, each entry an array of every accepted answer — e.g. [["8","eight"]] (one blank, two spellings) or [["a"],["b"]] (two blanks).
7. Optional: "source" (string, where it came from), "image" (an image URL or a data:image/...;base64 string, or an array of them).
8. Include EVERY question. Use only the answer the material marks correct. If none is marked, still include the question, choose the best-supported option, and add "source": "answer unverified". Never drop a question.
9. Straight ASCII double quotes only. The output must be valid UTF-8 JSON that JSON.parse accepts.

REQUIRED SHAPE (match this exactly)
[
  {"id":"q1","question":"Which fabric is approved for aircraft covering?","choices":["Polyester","Cotton bedsheet","Nylon tarp"],"answer":0,"source":"Chapter 3"},
  {"id":"q2","question":"Select ALL tools required. (multiple answers)","choices":["Punch tester","Hammer","Maule tester"],"answers":[0,2]},
  {"id":"q3","type":"fill","question":"A hole smaller than ____ inches may be patched.","blanks":[["8","eight"]]}
]

Before finishing, silently check: top level is [ ]; every object has "id" and "question"; each single-choice "answer" is a 0-based integer in range; multiple answers use "answers"; fill uses "type":"fill" plus "blanks"; no code-fence lines; no trailing commas. Put exactly that JSON array into the bank.json file (or inline only if you cannot make a file) — nothing else.

=== MATERIAL ===

The importer auto-handles a few common AI slips (code fences, an outer {"questions":[…]} wrapper, a missing id) — but the rules below still matter. / 导入器会自动兜底几种常见小毛病(代码围栏、外层 {"questions":[…]} 包裹、缺 id),但下面的规则仍需遵守。

English

A bank is a JSON array of question objects. Three question types are supported: single-choice, multiple-answer, and fill-in-the-blank.

Fields

FieldRequiredMeaning
id✅ every questionUnique string within the file, e.g. "ch3-12". Progress (wrong/star records) is keyed on it.
question✅ (unless image present)The stem, plain text. \n makes a line break.
choices✅ for choice questionsArray of at least 2 strings.
answersingle-choice0-based index into choices (first choice = 0).
answersmultiple-answerArray of 0-based indexes, e.g. [0,2]. Player switches to checkboxes automatically; all must match.
typefill-in onlySet "fill" (or just provide blanks).
blanksfill-inOne array per blank, each listing the accepted answers: [["8","eight"]] = 1 blank with 2 accepted spellings; [["a"],["b"]] = 2 blanks.
question_htmloptional (fill-in)HTML stem with <input data-blank="1"> placed where blanks belong (1-based). Omit it and inputs are appended below the stem.
answer_setsoptional (fill-in)Alternative whole-row combinations; any ONE set matching counts as correct.
imageoptionalImage URL or base64 data:image/... string — or an array of them. Shown above the choices.
sourceoptionalWhere the question came from; shown small under the card.

Grading rules

If it says “invalid / no valid questions” — why a record is skipped, and the fix

SymptomFix
Whole file rejected (“Not valid JSON”)It must be valid JSON. Remove markdown code fences, comments, and trailing commas; use straight " quotes.
“No valid questions found”Top level must be a bare array […]. Don’t wrap it as {"questions":[…]}. (The importer tries to unwrap, but a bare array is safest.)
Every question skippedUsually a missing id or a bad answer. Give each a unique id; make answer a 0-based integer in range (not the text, not 1-based).
One question skippedChoice Q needs choices (2+) and a valid answer/answers; fill-in needs blanks with at least one accepted answer; or give it an image if there’s no stem text.

中文

题库就是一个 JSON 数组,每个元素是一道题。支持三种题型:单选、多选、填空。

Complete example / 完整示例

[
  {
    "id": "demo-1",
    "question": "Which fabric is approved for aircraft covering?",
    "choices": ["Polyester", "Cotton bedsheet", "Nylon tarp", "Canvas drop cloth"],
    "answer": 0,
    "source": "Chapter 3 – Coverings"
  },
  {
    "id": "demo-2",
    "question": "Select ALL tools required for fabric testing. (multiple answers)",
    "choices": ["Punch tester", "Hammer", "Maule tester", "Torque wrench"],
    "answers": [0, 2]
  },
  {
    "id": "demo-3",
    "type": "fill",
    "question": "A hole smaller than ____ inches may be repaired with a doped-on patch.",
    "blanks": [["8", "eight"]]
  },
  {
    "id": "demo-4",
    "question": "Identify the part shown in the image.",
    "image": "https://example.com/part-diagram.png",
    "choices": ["Rib", "Spar", "Longeron"],
    "answer": 1
  }
]

Save as e.g. my-bank.json → catalog page → “Import your own bank”. The Extractor's “导出全部合并 JSON” produces exactly this format. / 保存为 .json 后到目录页导入即可;提取器导出的合并 JSON 就是这个格式。