Skip to content

feat: expose json.dumps kwargs in save_as_json - #725

Open
Abdur-Rafay-AR wants to merge 1 commit into
docling-project:mainfrom
Abdur-Rafay-AR:feat/save-as-json-kwargs
Open

feat: expose json.dumps kwargs in save_as_json#725
Abdur-Rafay-AR wants to merge 1 commit into
docling-project:mainfrom
Abdur-Rafay-AR:feat/save-as-json-kwargs

Conversation

@Abdur-Rafay-AR

Copy link
Copy Markdown

Addresses docling-project/docling#3939 (filed on docling, but the code lives here).

Problem

DoclingDocument.save_as_json hardcodes the json.dumps call:

filename.write_text(json.dumps(out, indent=indent), encoding="utf-8")

ensure_ascii is never passed, so it takes the stdlib default of True and every non-ASCII character is written as a \uXXXX escape. There is no way to override this from the public signature. The reporter hit it with Polish text, and the same thing happens with Urdu, CJK, and anything else outside ASCII. The current workaround is to reload every document and re-save it with the json module directly, which is not practical on large datasets.

Change

Adds an optional json_kwargs: Optional[dict[str, Any]] = None at the end of the signature, merged into the json.dumps call:

dump_kwargs: dict[str, Any] = {"indent": indent}
if json_kwargs:
    dump_kwargs.update(json_kwargs)
filename.write_text(json.dumps(out, **dump_kwargs), encoding="utf-8")

json_kwargs is merged last so a caller can override indent without triggering a TypeError on a duplicate keyword.

Usage:

doc.save_as_json("out.json", json_kwargs={"ensure_ascii": False})

Backward compatibility

The change is purely additive. Every existing parameter keeps its position and default, and the new argument is the last one, so positional callers are unaffected. When json_kwargs is omitted the output is byte for byte what it was before.

The new test pins this explicitly. It asserts not only that ensure_ascii=False writes the literal characters, but also that the default path still emits the escaped form, so a future regression in either direction fails the suite:

# Without json_kwargs the stdlib default still applies, so existing callers are unaffected.
escaped_file = tmp_path / "escaped.json"
doc.save_as_json(filename=escaped_file)
escaped = escaped_file.read_text(encoding="utf-8")
assert polish_text not in escaped
assert "Nale\u017cy" in escaped

The existing save_as_json calls covered by the ground truth snapshots were deliberately left untouched.

On save_as_yaml

save_as_yaml has the equivalent gap for a different reason: PyYAML's allow_unicode defaults to False, so the yaml.dump call escapes non-ASCII too. I left it out to keep this diff focused on the reported issue, but an equivalent yaml_kwargs is a small addition and I am happy to fold it into this PR if you want the two methods to stay consistent. Just say the word.

Context

I commented on the issue two days ago proposing this approach and asking whether you wanted one method or both, and a passthrough dict or explicit named parameters. Rather than let it sit, I am opening the narrow version so there is something concrete to review. Happy to reshape it if you would prefer named parameters such as ensure_ascii over a dict.

Testing

ruff check, ruff format --check, and mypy are clean on the changed files. The compat projector and docs generation hooks report no changes, as expected, since a method parameter does not affect the exported schema.

For the test suite, I compared the full run with and without the patch on the same environment and the set of failing tests is byte for byte identical, so this change introduces no regressions. test/test_docling_doc.py goes from 73 to 74 passing with the new test.

One unrelated note, offered as an observation rather than something I touched: several tests in test/test_docling_doc.py fail on Windows because _verify_saved_output compares serialized artifact paths literally, so the generated extracted_images\image_000 does not match the extracted_images/image_000 in the ground truth files. That failure cascades into test_concatenate and test_file_uri_allowed_with_env_var, which depend on a file the failing test would have written. Normalizing the separator before comparison would make the suite portable, but it is outside the scope of this PR.

Signed-off-by: Abdur Rafay <abdurrafay.tech@gmail.com>
@github-actions

Copy link
Copy Markdown
Contributor

DCO Check Passed

Thanks @Abdur-Rafay-AR, all your commits are properly signed off. 🎉

@mergify

mergify Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🔴 1 of 2 protections blocking · waiting on 👀 reviews

Protection Waiting on
🔴 Require two reviewer for test updates 👀 reviews
🟢 Enforce conventional commit

🔴 Require two reviewer for test updates

Waiting for

  • #approved-reviews-by >= 2
This rule is failing.

When test data is updated, we require two reviewers

  • #approved-reviews-by >= 2

Show 1 satisfied protection

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\(.+\))?(!)?:

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