Skip to content

Auto-convert plain dicts to DADict for checkboxes fields via API - #984

Closed
jacobyoby wants to merge 1 commit into
jhpyle:masterfrom
jacobyoby:fix/issue-981-dict-to-dadict-checkboxes
Closed

Auto-convert plain dicts to DADict for checkboxes fields via API#984
jacobyoby wants to merge 1 commit into
jhpyle:masterfrom
jacobyoby:fix/issue-981-dict-to-dadict-checkboxes

Conversation

@jacobyoby

Copy link
Copy Markdown

Summary

Fixes #981

When driving an interview via the API, submitting a plain dictionary like {"a": True, "b": False} for a checkboxes field creates a plain Python dict instead of a DADict. This breaks interviews that later call .true_values() or other DADict methods on the value.

Root cause

In docassemble_webapp/docassemble/webapp/interview/views.py, the code that processes submitted values for checkboxes/multiselect fields only handles string values ("True", "False"). When raw_data is a dict, none of the string comparisons match, so it falls through to data = "None" — silently discarding the dict value.

Fix

Added an isinstance(raw_data, dict) check before the string comparisons in both code paths that handle checkboxes values:

  1. Line ~1337 — bracket-expression keys (e.g. my_var[a])
  2. Line ~1510 — top-level keys (e.g. my_var)

When raw_data is a dict, the fix generates a DADict(...) construction string (with elements=raw_data) that gets exec()'d like other variable assignments, producing a proper DADict that supports .true_values(), .false_values(), etc.

The not isinstance(raw_data, bool) guard prevents false matches since bool is a subclass of int in Python.

Verified behavior

Input Datatype Result
{"a": True, "b": False} checkboxes DADict with elements, .true_values() returns ["a"]
"True" checkboxes True (unchanged)
"False" checkboxes False (unchanged)
{} checkboxes Empty DADict
None checkboxes None (unchanged)
{"x": True} multiselect DADict with elements

@jhpyle

jhpyle commented Sep 1, 2026

Copy link
Copy Markdown
Owner

This code is in the handler for the /interview endpoint, which expects to receive a POST request from the browser with Content-Type of application/x-www-form-urlencoded; charset=UTF-8. post_data is created with request.form.copy() and raw_data is a value from that MultiDict. Under what circumstances would raw_data be a dict?

@jacobyoby
jacobyoby force-pushed the fix/issue-981-dict-to-dadict-checkboxes branch from 38146e6 to 705e088 Compare September 1, 2026 14:02
The API stored a plain dict sent for a checkboxes variable as-is, and
the next assembly failed on the missing DADict interface (issue jhpyle#981).
A non-empty dict whose values are all booleans is now converted to a
gathered DADict before assignment, using the same exec pattern the
surrounding assignments use. Empty dicts are left alone: with no
values there is no signal the variable is checkbox-shaped.
@jacobyoby
jacobyoby force-pushed the fix/issue-981-dict-to-dadict-checkboxes branch from 705e088 to 1f8a541 Compare September 1, 2026 17:27
@jacobyoby

Copy link
Copy Markdown
Author

Never. 😅

request.form only ever gives strings, so that check was dead code where I had it. I've redone the PR: the conversion is now in set_session_variables, where variables comes from json in POST /api/session — the only place a dict would show up (which is how I hit #981 in the first place, driving interviews through the API). The /interview handler is untouched now and i tried to reduce to smallest possible change.

@jhpyle

jhpyle commented Sep 1, 2026

Copy link
Copy Markdown
Owner

With the existing code, you can set a variable to be a DADict if you want, or you can set a variable to be a dict if you want. See https://docassemble.org/docs/api.html#session_post_objects

So I don't see why this is necessary. Also code change in this PR would make it impossible to use the API to define a variable like payload = {'error': False}, which a user might want to do.

@jacobyoby

Copy link
Copy Markdown
Author

I appreciate the feedback! Seems to be working as designed.

@jacobyoby jacobyoby closed this Sep 1, 2026
@jacobyoby
jacobyoby deleted the fix/issue-981-dict-to-dadict-checkboxes branch September 2, 2026 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Accept plain dictionaries on checklist pages when driving via API?

2 participants