Skip to content

fix: write and read figure JSON as UTF-8#5633

Draft
LukeTheoJohnson wants to merge 1 commit into
plotly:mainfrom
LukeTheoJohnson:fix-json-io-utf8-encoding
Draft

fix: write and read figure JSON as UTF-8#5633
LukeTheoJohnson wants to merge 1 commit into
plotly:mainfrom
LukeTheoJohnson:fix-json-io-utf8-encoding

Conversation

@LukeTheoJohnson

@LukeTheoJohnson LukeTheoJohnson commented Jun 27, 2026

Copy link
Copy Markdown

Problem

pio.write_json(fig, path) raises UnicodeEncodeError for any figure containing non-ASCII text (titles, axis labels, hover text, categorical values such as °C, café, µ) on platforms whose default text encoding is not UTF-8. On Windows the default is cp1252:

fig.update_layout(title="Café µ")
pio.write_json(fig, "fig.json")
# UnicodeEncodeError: 'charmap' codec can't encode characters ...

read_json has the same bug. It reads the file without specifying an encoding, so a UTF-8 JSON file is decoded as cp1252 and the text comes back as mojibake. This works on macOS/Linux only because their default encoding happens to be UTF-8.

Root cause

plotly/io/_json.py opened the file without an encoding on both sides:

  • write_json: path.write_text(json_str)
  • read_json: path.read_text()

write_html already does this correctly (path.write_text(html_str, "utf-8")), and the same class of bug was previously fixed for HTML output (#3898). I believe the JSON I/O path was simply missed.

Fix

Pass "utf-8" explicitly in both write_json and read_json, matching write_html. JSON is UTF-8 by default per RFC 8259.

Tests

  • Updated the existing test_write_json_pathlib and test_read_json_from_pathlib to assert the UTF-8 encoding is used. Verified red to green: both fail on the unpatched source and pass with the fix.
  • Confirmed a real write_json to read_json return of a non-ASCII figure returns the original text on Windows (cp1252).
  • No new regressions: tests/test_io/test_to_from_json.py shows only the pre-existing FigureWidget ImportErrors (anywidget not installed).

Scope

Small source change plus test assertions. No behaviour change on platforms that already default to UTF-8.

write_json wrote figure JSON with Path.write_text(json_str) and read_json
read it back with Path.read_text(), both omitting the encoding. On platforms
whose default text encoding is not UTF-8 (e.g. cp1252 on Windows), writing a
figure containing non-ASCII text raised UnicodeEncodeError and reading produced
mojibake. write_html already passes "utf-8" explicitly; apply the same to the
JSON I/O path so figures round-trip everywhere.

Update the existing pathlib mock tests to assert the UTF-8 encoding.
@LukeTheoJohnson LukeTheoJohnson force-pushed the fix-json-io-utf8-encoding branch from b6cbd44 to 1c182c4 Compare June 27, 2026 01:38
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.

1 participant